I want to retrieve member size of Contact Group. I am using below URL.
String pageUrl="https://www.google.com/m8/feeds/contacts/default/full/" +
"?xoauth_requestor_id="+userEmail+"&group="+groupId;
It is retrieving by default 25 records.Though there are more than 25 records. how can i retrieve size of contact group..? Which url i need to use.?
pageUrl += "&max-results=10000"
Related
I'm trying to get the Url of Gmail messages and store them into a Google Sheet. I'm doing this because the sheet will serve as a dashboard and I want to be able to link to specific messages which can be quickly opened by clicking the message hyperlink.
Gmail message urls will start with something like "https://mail.google.com/mail/u/0/?pli=1#inbox/" for messages in the 'inbox' followed by a string of around 70 characters representing a message ID such as "ZhatKJWQfkVxNWLWSctJlTPzJAjLTGmHOFwlqPWVTvjkwVgsnhBsfmJrrvjRDAHfKozQnYn".
As far as I can tell there is no way to get the full url from the GMail Message class. However you can retrieve the message id using getId().
So my approach was to retrieve the ID, append it to the inbox prefix ("https://mail.google.com/mail/u/0/?pli=1#inbox/") and that should create the link as follows:
for (var x = messageThread.length-1; x>=0; x--) {
for (var y = 0; y< numMessagesInThread; y++) {
var message = messageThread[x].getMessages()[y];
var messageId = message.getId();
var messageUrl = "https://mail.google.com/mail/u/0/?pli=1#inbox/" + messageId;
...
The problem is it turns out getId() doesn't return the 70 character Id in the original Url of the message but rather a 16 character Id such as "2487g294ie3f3x8z". Needless to say when used in the URL it doesn't work.
I'm stuck at this point and have been searching for a way to do this, if anyone has ideas would be greatly appreciated.
I’m trying to access Maps from a script bound to a Google form. The problem i’m having is that when debugging the script, it accesses Maps so often that i’m Running into quota limits. I have a Maps API key but do not have a client ID so can’t get Maps.setAuthenication(clientID,Key) to work. I’m doing this for a Scout Troop so don’t want to have to pay to access maps.
Can anyone help?
I was subsequently asked to post my code, and so here it is:
function setLocation(){
var whereString;
var theDuration;
var theDistance;
var theRoute;
var theDirections;
var theTravelString;
// this Sets the Where: Tab on the form
whereString = 'Where: ' + gLocation;
theItemArray = gSignupForm.getItems();
theItemArray[kWhereItem].setTitle(whereString);
//this gets the directions to the location
Maps.setAuthentication('','ABCDEFGHIJKLMNOP');
//Obviously Im'm not going to post the true key
theDirections = Maps.newDirectionFinder()
.setOrigin('7101 Shadeland Ave, Indianapolis, IN 46256')
.setDestination(gLocation)
.setMode(Maps.DirectionFinder.Mode.DRIVING)
.getDirections();
theRoute = theDirections.routes[0];
theDuration = theRoute.legs[0].duration.text;
theDistance = theRoute.legs[0].distance.text;
theTravelString = Utilities.formatString('Travel Considerations: The estimated travel distance is %u miles. ',theDistance);
theTravelString += 'The estimated travel time is ' + theDuration;
theItemArray[kTravelItem].setTitle(theTravelString);
}
One solution to limit the use of low-quota services is to avoid calling those services when the desired information has not changed.
For example, through the use of CacheService, you can dramatically reduce your calls to the Maps API, debugging session or not:
var cache = CacheService.getScriptCache();
function setLocation() {
// Try to find the route for this location if it's still available
var storedRoute = cache.get(gLocation);
if (!storedRoute) {
// No route for this value of the key gLocation was found. Query as normal.
...
theRoute = theDirections.route[0];
// Cache this route for future uses, for the maximum of 6hr).
cache.put(gLocation, JSON.stringify(theRoute), 21600);
} else {
// We have this exact stored route! Convert it from the stored string.
theRoute = JSON.parse(storedRoute);
}
theDuration = ...
...
Your "gLocation" variable may be directly usable as a cache key. If not, you'll need to make it useable by encoding it. The max length key is 250 characters. This single-parameter caching assumes your directions all have a fixed endpoint, as shown in your example code. If both endpoints vary, you'll have to construct a cache key based on both values.
Related question: Maps direction Quota limits
I have a C# Console application that uses EWS (Exchange Web Services) to impersonate a user and I create or update his current Contacts list.
In order to determine if I have to create or update his list, I first need to search his existing Contacts for a particular domain name like so:
private static IEnumerable<Contact> GetExistingContacts(ExchangeService service)
{
var domainToFilterOn = "#contoso.com";
SearchFilter sfSearch = new SearchFilter.ContainsSubstring(ContactSchema.EmailAddress1, domainToFilterOn);
FindItemsResults<Item> contacts = service.FindItems(WellKnownFolderName.Contacts, sfSearch, new ItemView(int.MaxValue));
var results = contacts.Cast<Contact>().ToList();
return results;
}
The problem I’m facing is that the method GetExistingContacts() yields 0 results for the given domain name which is wrong since I know I have a bunch of Contacts holding the #contoso.com domain name inside the EmailAddre1 field.
After a little bit of digging and testing, I finally figure out why the method wasn’t returning any results and the reason was because the email addresses are stored in the Exchange distinguished name instead of the SMTP format.
To further my investigation, I created a few new Contacts with fake/non-existing #contoso.com domain name like: test#contoso.com, gazou#contoso.com, etc.
To my surprise, the GetExistingContacts() method started to return these fake Contacts.
The conclusion is that whenever I create new Contacts that have resolvable email addresses, then these Contacts are stored using the Exchange distinguished name but when I create new Contacts that have non-resolvable email addresses, then these Contacts are stored as SMTP (which are returned by my GetExistingContacts() method).
How do I start fixing this?
Is my search method wrong? Is there another way to search inside the EmailAddress1 field?
Meanwhile, I managed to find a workaround using the .Load() method of the Contact object but this workaround seems ugly and costly in terms of execution time.
I basically get all Contacts, loop and call the Load() method, then add them to a List() and make a Linq query to filter the results. If my user has 800 Contacts, that takes a long time to Load() everyone of them.
Here’s the example:
private static IEnumerable<Contact> GetCurrentContacts(ExchangeService service)
{
var contacts = new List<Contact>();
var data = service.FindItems(WellKnownFolderName.Contacts, new ItemView(int.MaxValue));
foreach (var item in data.Items)
{
if (item is Contact)
{
item.Load();
contacts.Add(item as Contact);
}
}
var result = contacts.Where(x => x.EmailAddresses[EmailAddressKey.EmailAddress1].Address.Contains("#contoso.com")).ToList();
return result;
}
Needless to say, I don't think that is the correct approach although it works.
Another alternative I’ve tried was to force the RoutingType to SMTP thinking it would create the new Contact in the SMTP format as opposed to the Exchange distinguished name but unfortunately, the email address still gets stored in the Exchange distinguished name disregarding the fact that I forced the RoutingType like so:
var email = new EmailAddress();
email.Address = "goodemail#contoso.com";
email.RoutingType = "SMTP";
Contact contact = new Contact(service);
contact.EmailAddresses[EmailAddressKey.EmailAddress1] = email;
...
contact.Save();
If anyone can help me shed some light on this, that would be great!
Thanks in advance
If the SMTP address your trying to use for a Contact is visible (or resolvable) in the Global address list then the X500 address of Directory entry will be used to track the Contact to the Directory entry (this is by design). If you want to return the SMTP address instead of the X500 address when you retrieve the contacts all you need to do is make use you do a GetItem or Load in the Managed API on the contact or contacts in question if you have multiple contact use LoadPropertiesFromItems https://blogs.msdn.microsoft.com/exchangedev/2010/03/16/loading-properties-for-multiple-items-with-one-call-to-exchange-web-services/
You can override this behavior by setting the extended properties on the contacts directly see https://social.technet.microsoft.com/Forums/exchange/en-US/2b375c56-bee1-4d88-b638-f95649ef964a/use-ews-create-a-contact-which-has-a-same-email-address-in-gal-it-will-show-up-with-x500-formatting?forum=exchangesvrdevelopment but I would recommended you stay with the default behavior you can make you code more efficient using batch Loads.
Thank you #Glen Scales, the LoadPropertiesForItems() helped.
This is the final result if anyone cares:
private static IEnumerable<Contact> GetExistingContacts(ExchangeService service)
{
var contacts = new List<Contact>();
var filterContactsOnDomain = "#contoso.com";
var data = service.FindItems(WellKnownFolderName.Contacts, new ItemView(int.MaxValue));
if (data.TotalCount > 0)
{
service.LoadPropertiesForItems(data, new PropertySet(ContactSchema.EmailAddress1));
foreach (var item in data.Items)
{
if (item is Contact)
{
contacts.Add(item as Contact);
}
}
}
var result = contacts.Where(x => x.EmailAddresses[EmailAddressKey.EmailAddress1].Address.ToLower().Contains(filterContactsOnDomain.ToLower())).ToList();
return result;
}
The only thing I dislike is having to get all Contacts (800 of them), load the EmailAddress1 field for all 800 of them, loop and add those 800 Contacts to a list and then, filter on that list...
I guess it would've been nice to have the ability to search (or filter) directly on an X500 email address format thus not having to fetch all 800 Contacts.
Oh well...
Thanks again #Glen Scales
I am working on Google search console data to get more than 1000 rows of data
through the search analytics API request.
Below is the request
request = {
'startDate': single_date,
'endDate': single_date,
'dimensions': ['query', 'page', 'date', 'country', 'device'],
'rowLimit': 5000,
'startRow': 0
}
According to the documentation specified in the below link.
https://developers.google.com/webmaster-tools/search-console-api-original/v3/how-tos/search_analytics#getting-more-than-5000-rows
If the result to the request sent has more than 5000 rows then it should display 5000 rows in the first request and
then we can request more 5000 rows after setting the start row to 5000 in the second request.
My Use case:
The request i am sending has more than 5000 rows but my result shown is as below:
-----Executing the first request---------start row as 0
row count 409
-----Executing the second request -------start row as 5000
row count 807 (adding the first and second request row count)
-----Executing the third request --------start row as 10000
row count 1218 (adding the first,second and third request row count )
this is continued till 10 requests ..
second Question related to the search console data
The total clicks displayed in the UI of the search analytics API is not same with - when we download the
excel sheet at the bottom and add all the clicks. In this case the data is present till the clicks become zero .
Could you please explain,
Thank you.
Since you need "all the queries per particular page on a date in a particular country and the particular device" (based on your comment), your dimension should be query and everything else should be a filter. Your request should look something like this:
request = {
'startDate': single_date,
'endDate': single_date,
'dimensions': ['query'],
'dimensionFilterGroups': [ {'groupType': 'and',
'filters': [{'dimension': 'country','operator': 'equals', 'expression': 'FRA'},
{'dimension': 'page', 'operator': 'equals', 'expression': '/about'},
{'dimension': 'device', 'operator': 'equals', 'expression': 'DESKTOP'}],
'rowLimit': 5000,
'startRow': 0
}
This request will give you up to 5000 queries that led to the page /about in France on desktop devices. You can change the filter expressions to the values you'd like to query.
I wrote a google apps script which fetches the G Suite (google apps) users from the AdminDirectory API
As on output, i get the domain name in front of every user (used replace to extract domain name from each user email id).
what i want to do-:
1. Count the number of users on each domain in one column, so end result should look like this-:
Column - I (exaxple)
domainA.com = 120 users
domainB.com = 28 users
etc....
Any help is appreciated.
I think there is probably a way to shorten this code, but something like this will work. You will have to figure out how to read the correct columns in and output to the correct columns, but hopefully, this will help out:
var emails = [
'someone#testA.com',
'someone#testB.com',
'someone#testA.com',
'someoneelse#testA.com'
];
function countDomains() {
var domainCounts = {};
var domains = emails.map(function(domain) {return domain.split('#')[1];});
domains.forEach(function(each) {
if(domainCounts.hasOwnProperty(each)) {
domainCounts[each]++;
} else {
domainCounts[each] = 1;
}
});
Logger.log(domainCounts);
}