https://sourceforge.net/project/showfiles.php?group_id=210092&package_id=252191&release_id=560658
Now supported:
- Import Google Mail contacts
- Import Yahoo Mail contacts
- Import Live contacts/Hotmail contacts
OpenContacts.NET 1.0 Alpha is released. Hosted on SourceForge.net.
Project link: OpenContacts.NET 1.0 (http://sourceforge.net/projects/opencontactsnet)
Please report bugs, feature requests on project page. Let me know if you what to participate.
Thanks
I was using special JavaScript for specifying default button in ASP.NET forms.
I've just found perfect solution: Imagine you created form in asp.net like
and you need to perform LoginButton click when user presses enter in Password field. Best solution: wrap your form in Panel control and specify DefaultButton property.
LoginButton will act like default button.
Thanks, Gnilly
// parse the mailbox information
ParseDataPack();
/**************************************************************************
Gmail Agent API
Copyright (C) 2005 Johnvey Hwang, Eric Larson
http://sourceforge.net/projects/gmail-api/
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**************************************************************************/
using System;
using System.Collections;
using System.Data;
using System.Web;
using System.Net;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
using Johnvey.GmailAgent;
namespace Johnvey.GmailAgent
{
///
/// Represents a set of tools used to communicate with the Gmail system.
///
public class GmailAdapter
{
#region Enumerations
///
/// Defines the result of a Gmail request.
///
public enum RequestResponseType
{
///
/// The request was successful.
///
Success,
///
/// The Google Accounts login information did not validate.
///
LoginFailed,
///
/// The DataPack request was not successful.
///
RefreshFailed
}
///
/// Defines the type of threads to retrieve.
///
public enum ThreadFetchType
{
///
/// All unread threads.
///
AllUnread,
///
/// All unread inbox threads.
///
Inbox
}
#endregion
#region Constants
///
/// Defines the URL to POST Google Accounts login information.
///
// modified login url to compensate for new login procedure
// Fix from Eric Larson [larson.eric@gmail.com]; 4/21/2005
public const string GOOGLE_LOGIN_URL = "https://www.google.com/accounts/ServiceLoginAuth";
///
/// Defines the URL to fake as the GOOGLE_LOGIN_URL's referrer. (I don't know if Google is checking this, but it can't hurt.)
///
// Changed login referrer according to what is currently being used (from my tests)
// Modified by Eric Larson [larson.eric@gmail.com]; 4/21/2005
public const string GOOGLE_LOGIN_REFERRER_URL = "https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=https%3A%2F%2Fmail.google.com%2Fmail%3Fui%3Dhtml%26zy%3Dl";
///
/// Defines the base URL for Gmail requests.
///
public const string GMAIL_HOST_URL = "https://mail.google.com";
///
/// Defines the URL to use in the post data "continue" variable on the initial connection
///
// modified login url to compensate for new login procedure
// Fix from Eric Larson [larson.eric@gmail.com]; 4/21/2005
public const string GOOGLE_LOGIN_CONTINUE = "https://mail.google.com/mail?";
///
/// Defines the URL to use when sending an invite.
///
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public const string GMAIL_INVITE_URL = "http://mail.google.com/mail?&view=ii";
///
/// Defines the URL to fake as the GOOGLE_INVITE_URL's referrer. (I don't know if Google is checking this, but it can't hurt.)
///
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public const string GMAIL_INVITE_REFERRER_URL = "http://mail.google.com/mail?&ik=&search=inbox&view=tl&start=0&init=1&zx=vik357vuzj2r";
///
/// Defines the URL to use when adding, editing, or deleting a label.
///
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public const string GMAIL_LABEL_URL = "http://mail.google.com/mail?&ik=&view=up";
///
/// Defines the URL to fake as the GOOGLE_LABEL_URL's referrer. (I don't know if Google is checking this, but it can't hurt.)
///
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public const string GMAIL_LABEL_REFERRER_URL = "http://mail.google.com/mail?&view=pr&pnl=l";
///
/// Defines the URL to use when adding, editing, or deleting a filter.
///
public const string GMAIL_FILTER_URL = "https://mail.google.com/mail?";
///
/// Defines the URL to fake as the GOOGLE_FILTER_URL's referrer. (I don't know if Google is checking this, but it can't hurt.)
///
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public const string GMAIL_FILTER_REFERRER_URL = "https://mail.google.com/mail?&pnl=f";
///
/// Defines the URL to use when adding or editing a contact.
///
public const string GMAIL_CONTACT_URL = "http://mail.google.com/mail?&ik=&view=up";
///
/// Defines the URL to use when deleting a contact.
///
public const string GMAIL_CONTACT_DELETE_URL = "http://mail.google.com/mail?";
///
/// Defines the URL to fake as the GOOGLE_CONTACT_URL's and GOOGLE_CONTACT_DELETE_URL's referrer. (I don't know if Google is checking this, but it can't hurt.)
///
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public const string GMAIL_CONTACT_REFERRER_URL = "http://mail.google.com/mail?&search=contacts&ct_id=1&cvm=2&view=ct";
#endregion
#region Properties
private string _jsVersion;
private GmailSession _session;
private string _rawLoginResponse;
private string _rawHomeFrameResponse;
private string _rawDataPackResponse;
private string _lastErrorMessage;
private ThreadFetchType _threadFetchMode;
private WebProxy _proxy;
private bool _commandSuccess;
private string _commandResponse;
///
/// Gets or sets the Gmail JS engine version.
///
public string JsVersion { get { return _jsVersion; } set { _jsVersion = value; } }
///
/// Gets the raw HTML content returned from the Google Accounts login request.
///
public string RawLoginResponse { get { return _rawLoginResponse; } }
///
/// Gets the raw HTML content returned from the Gmail base launch request.
///
public string RawHomeFrameResponse { get { return _rawHomeFrameResponse; } }
///
/// Gets the raw HTML content returned from a DataPack request.
///
public string RawDataPackResponse { get { return _rawDataPackResponse; } }
///
/// Gets the last error message generated by the GmailAdapter methods. Will be null if there are no errors.
///
public string LastErrorMessage { get { return _lastErrorMessage; } }
///
/// Gets or sets thefor the adapter. The default is Inbox .
///
public ThreadFetchType ThreadFetchMode { get { return _threadFetchMode; } set { _threadFetchMode = value; } }
///
/// Gets or sets the proxy for HTTP requests. Leave null for no proxy support.
///
public WebProxy Proxy { get { return this._proxy; } set { this._proxy = value; } }
///
/// Gets or sets the Gmail success status of the current request.
///
public bool CommandSuccess { get { return _commandSuccess; } set { _commandSuccess = value; } }
///
/// Gets or sets the Gmail success message of the current request.
///
public string CommandResponse { get { return _commandResponse; } set { _commandResponse = value; } }
#endregion
///
/// Initializes a new instance of the GmailAdapter class.
///
public GmailAdapter()
{
/**********************************************************************
* These ServicePointManager settings are here because the .NET
* Framework (1.0 and 1.1) don't like to play well with other web
* servers. Some of these are arbitrary hacks that have been
* suggested over the newsgroups. The one that seems to work
* constistently is using TLS instead of SSL3. Go figure.
* NOTE: the Expect100Continue property is not supportted in .NET 1.0.
* *******************************************************************/
// ServicePointManager.CertificatePolicy = new GmailCertificatePolicy();
ServicePointManager.Expect100Continue = false;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
this._lastErrorMessage = null;
this._threadFetchMode = ThreadFetchType.Inbox;
this._proxy = null;
}
///
/// Represents a delegate for themethod.
///
public delegate RequestResponseType RefreshDelegate(GmailSession session);
///
/// Queries Gmail to get latest mailbox information.
///
/// Theobject to query.
///The .
public RequestResponseType Refresh(GmailSession session)
{
// bring focus to active session
this._session = session;
// make sure there is proper login information
if (this._session.Username == "" || this._session.Username == null || this._session.Password == "" || this._session.Password == null)
{
return RequestResponseType.LoginFailed;
}
// if it's been a while since we logged in, do it again to keep the cookie fresh
if (session.LastLoginTime == new DateTime(0) || session.LastLoginTime < DateTime.Now.AddHours(-1))
{
if (Login())
{
return RequestResponseType.Success;
}
else
{
return RequestResponseType.LoginFailed;
}
}
else
{
if (RefreshDataPack(false))
{
return RequestResponseType.Success;
}
else
{
return RequestResponseType.RefreshFailed;
}
}
}
///
/// Sends Google Accounts login stored in the currentand establishes a session with Gmail.
///
///True if login was successful; false otherwise.
private bool Login()
{
// grab the user's cookie store
CookieCollection cookieJar = this._session.Cookies;
// put some cookies in it
GmailCookieFactory tollHouse = new GmailCookieFactory();
cookieJar.Add(tollHouse.GenerateCookie("GMAIL_LOGIN"));
cookieJar.Add(tollHouse.GenerateCookie("TZ"));
// instantiate the key pieces
Uri location;
string rawResponse;
int currentCursor;
/**********************************************************************
* Login to Google Accounts
* -- parse response to get the GV cookie (don't know what it's for)
* *******************************************************************/
// modified post data to compensate for new login procedure
// service=mail is necessary
// rm=false is not necessary, but appeared during testing so I left it
// Fix from Eric Larson [larson.eric@gmail.com]; 4/21/2005
string loginPostData = "continue=" + System.Web.HttpUtility.UrlEncode(GOOGLE_LOGIN_CONTINUE)
+ "&service=mail"
+ "&rm=false"
+ "&Email=" + System.Web.HttpUtility.UrlEncode(this._session.Username)
+ "&Passwd=" + System.Web.HttpUtility.UrlEncode(this._session.Password)
+ "&null=Sign+in";
location = new Uri(GOOGLE_LOGIN_URL);
// try the request; catch any unhandled exceptions
try
{
rawResponse = MakeWebRequest(location, "POST", GOOGLE_LOGIN_REFERRER_URL, loginPostData, false);
}
catch (Exception ex)
{
this._session.HasConnectionError = true;
this._lastErrorMessage = "Unable to log in to Google Accounts: " + ex.Message;
return false;
}
// catch empty response and bad login
if (rawResponse == null || rawResponse == "")
{
this._session.HasConnectionError = true;
this._lastErrorMessage = "Unable to log in to Google Accounts: empty response document!";
return false;
}
else if (Regex.Match(rawResponse, "password.+not.+match", RegexOptions.Compiled).Success)
{
this._session.HasConnectionError = true;
this._lastErrorMessage = "Unable to log in to Google Accounts: Username (" + this._session.Username + ") and password do not match.";
return false;
}
this._rawLoginResponse = rawResponse;
// get _sgh variable from login response
string var_sgh = "";
currentCursor = rawResponse.IndexOf("_sgh");
if (currentCursor > -1)
{
int varDeclStart = rawResponse.IndexOf("_sgh%3D", currentCursor) + 7;
int varDeclEnd = rawResponse.IndexOf("&", varDeclStart + 5, 40);
var_sgh = rawResponse.Substring(varDeclStart, varDeclEnd - varDeclStart);
}
else
{
this._lastErrorMessage = "Unable to find _sgh GET variable.";
}
/**********************************************************************
* Request Gmail home application frame
* -- store GMAIL_AT and S cookies passed in the header
* -- parse response to get Gmail engine version (jsVersion)
* *******************************************************************/
location = new Uri(GMAIL_HOST_URL + "/mail?_sgh=" + var_sgh);
try
{
rawResponse = MakeWebRequest(location, "GET", GOOGLE_LOGIN_URL, null, false);
}
catch (Exception ex)
{
this._lastErrorMessage = "Error retrieving Gmail home frame page: " + ex.Message;
return false;
}
this._rawHomeFrameResponse = rawResponse;
// get JS version ID
this._jsVersion = "jsVersionNotFound";
Match m = Regex.Match(rawResponse, @"\&ver=([a-z0-9]+)", RegexOptions.Compiled);
if (m.Success)
{
this._jsVersion = m.Groups[1].Value;
}
else
{
this._lastErrorMessage = "Unable to find JS Gmail engine version.";
}
/**********************************************************************
* Request initial dataPack page and extract mailbox information
* *******************************************************************/
switch (this._threadFetchMode)
{
case ThreadFetchType.AllUnread:
location = new Uri(GMAIL_HOST_URL + "/mail?search=query&q=is%3Aunread&view=tl&start=0&init=1&zx=" + MakeUniqueUrl());
break;
case ThreadFetchType.Inbox:
location = new Uri(GMAIL_HOST_URL + "/mail?search=inbox&view=tl&start=0&init=1&zx=" + MakeUniqueUrl());
break;
default:
break;
}
try
{
rawResponse = MakeWebRequest(location, "GET", null, null, false);
}
catch (Exception ex)
{
this._session.HasConnectionError = true;
this._lastErrorMessage = "Unable to retrieve initial DataPack document: " + ex.Message;
return false;
}
if (rawResponse == "" || rawResponse == null)
{
this._session.HasConnectionError = true;
this._lastErrorMessage = "Initial DataPack document did not contain any data.";
return false;
}
Debug.WriteLine(rawResponse);
this._rawDataPackResponse = rawResponse;
// mark login time
this._session.LastLoginTime = DateTime.Now;
// parse the mailbox information
//ParseDataPack();
this._session.LastRefreshTime = DateTime.Now;
this._session.HasConnectionError = false;
return true;
}
///
/// Requests the auto-refresh DataPack.
///
///
/// If the threadlist timestamp has not changed, Gmail will only send a short DataPack.
///
/// DEBUG: Indicates whether to pass an old timestamp, which forces Gmail to resend a full DataPack.
public bool RefreshDataPack(bool forceRefresh)
{
string tlt;
// DEBUG: setting the timestamp to an older time forces Gmail to return a full DataPack
if (forceRefresh)
{
tlt = "fd44c8cfc2";
}
else
{
tlt = this._session.ThreadListTimestamp;
}
string fp = this._session.Fingerprint;
Uri location = null;
switch (this._threadFetchMode)
{
case ThreadFetchType.AllUnread:
location = new Uri(GMAIL_HOST_URL + "/mail?view=tl&search=query&start=0&q=is%3Aunread&tlt=" + tlt + "&fp=" + fp + "&auto=1&zx=" + MakeUniqueUrl());
break;
case ThreadFetchType.Inbox:
location = new Uri(GMAIL_HOST_URL + "/mail?view=tl&search=inbox&start=0&tlt=" + tlt + "&fp=" + fp + "&auto=1&zx=" + MakeUniqueUrl());
break;
default:
break;
}
try
{
this._rawDataPackResponse = MakeWebRequest(location, "GET", "http://mail.google.com/mail/html/hist2.html", null, false);
}
catch (Exception ex)
{
this._session.HasConnectionError = true;
this._lastErrorMessage = "Unable to refresh DataPack document: " + ex.Message;
return false;
}
if (this._rawDataPackResponse == "" || this._rawDataPackResponse == null)
{
this._lastErrorMessage = "Initial DataPack document did not contain any data.";
return false;
}
ParseDataPack();
this._session.LastRefreshTime = DateTime.Now;
return true;
}
#region Contacts
///
/// Retrieves all the contacts in the user's Gmail address book.
///
///A of contacts in address book.
public GmailContactCollection GetContacts()
{
// instantiate output vars
GmailContactCollection output = new GmailContactCollection();
// Added the IK the URI to the fit the current protocol
// Fix by Eric Larson [larson.eric@gmail.com]; 5/2/2005
Uri location = new Uri(GMAIL_HOST_URL + "/mail?&ik=" + System.Web.HttpUtility.UrlEncode(this._session.IdentificationKey) + "&view=cl&search=contacts&pnl=a&zx=" + MakeUniqueUrl());
this._rawDataPackResponse = MakeWebRequest(location, "GET", null, null, true);
// sanitize the incoming _rawDataPackResponse
this._rawDataPackResponse = this._rawDataPackResponse.Replace("\n", "");
if (this._rawDataPackResponse.Length > 128)
{
// Looping through the data pack response looking for multiple arrays
// Gmail only puts 15 address in a single array, so search all 'a' (address) arrays.
// Fix by Eric Larson [larson.eric@gmail.com]; 5/2/2005
//int addressBlockStart = this._rawDataPackResponse.IndexOf("D([\"a\"");
// Fix by Billy Roebuck [billyroebuck@yahoo.com.au]; 6/24/2005
// Changed the line below (and again at the end of this method) and some of the offset values
//int addressBlockStart = this._rawDataPackResponse.IndexOf("D([\"a\"");
int addressBlockStart = this._rawDataPackResponse.IndexOf("D([\"cl\",");
while (addressBlockStart > -1)
{
// find the address block
addressBlockStart = this._rawDataPackResponse.IndexOf("[", addressBlockStart + 6);
int addressBlockEnd = this._rawDataPackResponse.IndexOf("]]);", addressBlockStart) + 1;
string addressBlock = "[" + this._rawDataPackResponse.Substring(addressBlockStart, addressBlockEnd - addressBlockStart) + "]";
//addressBlock = addressBlock.Replace("\\\\\\\"", "\"");
// parse the address block into an ArrayList
ArrayList addresses = Utilities.ParseJSArray(addressBlock);
// loop through ArrayList of contacts and insert into collection
foreach (ArrayList contact in addresses)
{
GmailContact tmpContact = new GmailContact();
// Using GmailContact Indeces enum for easy changing
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
// Store the contact ID so that we can edit or delete it.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
tmpContact.id = int.Parse((string)contact[(int)GmailContact.Indeces.id], System.Globalization.NumberStyles.HexNumber);
tmpContact.Email = contact[(int)GmailContact.Indeces.Email].ToString();
tmpContact.Name = contact[(int)GmailContact.Indeces.DefaultName].ToString();
if (contact.Count > (int)GmailContact.Indeces.Notes)
{
tmpContact.Notes = contact[(int)GmailContact.Indeces.Notes].ToString();
}
// EmailUnescaped is no longer sent by Gmail, so fake it.
// to keep backwards compatibility with 0.6.1 and before
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
tmpContact.EmailUnescaped = System.Web.HttpUtility.HtmlEncode(contact[(int)GmailContact.Indeces.Email].ToString());
// Frequently mailed can no longer be be determined in a single request.
// So initialize all contacts to false and then make second request later.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
tmpContact.IsFrequentlyMailed = false;
output.Add(tmpContact);
}
// Check to see if there is another block of contacts.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
//addressBlockStart = this._rawDataPackResponse.IndexOf("D([\"a\"", addressBlockStart);
// Fix by Billy Roebuck [billyroebuck@yahoo.com.au]; 6/24/2005
addressBlockStart = this._rawDataPackResponse.IndexOf("D([\"cl\",", addressBlockStart);
} ;
}
// Pass the current list of contacts to a helper function to find the frequently mailed contacts.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
GetFrequentlyMailedContacts(output);
return output;
}
///
/// Updates IsFrequentlyMailed flag in the contacts collection.
/// If the contact is not found in the current collection, it is added.
/// Helper function of GetContacts to update the contacts collection.
///
/// List of Gmail contacts; should be all contacts.
///A of contacts in address book.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
private void GetFrequentlyMailedContacts(GmailContactCollection contacts)
{
//frequently mailed
Uri location = new Uri(GMAIL_HOST_URL + "/mail?&ik=" + System.Web.HttpUtility.UrlEncode(this._session.IdentificationKey) + "&view=cl&search=contacts&pnl=d&zx=" + MakeUniqueUrl());
this._rawDataPackResponse = MakeWebRequest(location, "GET", null, null, true);
// sanitize the incoming _rawDataPackResponse
this._rawDataPackResponse = this._rawDataPackResponse.Replace("\n", "");
if (this._rawDataPackResponse.Length > 128)
{
// find the beginning of the address block
// Fix by Billy Roebuck [billyroebuck@yahoo.com.au]; 6/24/2005
// Changed the line below (and again at the end of this method) and some of the offset values
//int addressBlockStart = this._rawDataPackResponse.IndexOf("D([\"a\"");
int addressBlockStart = this._rawDataPackResponse.IndexOf("D([\"cl\",");
// make multiple passes to parse all address arrays
while (addressBlockStart > -1)
{
// find the address block beginning and end
addressBlockStart = this._rawDataPackResponse.IndexOf("[", addressBlockStart + 8);
int addressBlockEnd = this._rawDataPackResponse.IndexOf("]]);", addressBlockStart) + 2;
// Need to enclose address block in quotes for ParseJSArray to parse it correctly.
// Fixed by Eric Larson [larson.eric@gmail.com]; 5/2/2005
// get the address block
string addressBlock = "[" + this._rawDataPackResponse.Substring(addressBlockStart, addressBlockEnd - addressBlockStart) + "]";
// parse the address block into an ArrayList
ArrayList addresses = Utilities.ParseJSArray(addressBlock);
// loop through ArrayList of contacts and insert into collection
foreach (ArrayList contact in addresses)
{
// Using GmailContact Indeces enum for easy changing
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
GmailContact currentContact = new GmailContact();
int i;
// loop through current contacts to update conatct collection
for (i = 0; i < contacts.Count; i++)
{
// Check the contact list to see if the frequently mailed contact is in the collection
currentContact = (GmailContact)contacts[i];
if (currentContact.id == int.Parse((string)contact[(int)GmailContact.Indeces.id], System.Globalization.NumberStyles.HexNumber))
{
currentContact.IsFrequentlyMailed = true;
break;
}
}
// If contact was not in the collection, add it
if (i == contacts.Count)
{
GmailContact tmpContact = new GmailContact();
tmpContact.id = int.Parse((string)contact[(int)GmailContact.Indeces.id], System.Globalization.NumberStyles.HexNumber);
tmpContact.Email = contact[(int)GmailContact.Indeces.Email].ToString();
tmpContact.Name = contact[(int)GmailContact.Indeces.DefaultName].ToString();
if (contact.Count > (int)GmailContact.Indeces.Notes)
{
tmpContact.Notes = contact[(int)GmailContact.Indeces.Notes].ToString();
}
// to keep backwards compatibility with 0.6.1 and before
tmpContact.EmailUnescaped = System.Web.HttpUtility.HtmlEncode(contact[(int)GmailContact.Indeces.Email].ToString());
tmpContact.IsFrequentlyMailed = true;
contacts.Add(tmpContact);
}
}
// Check to see if there is another block of contacts.
//addressBlockStart = this._rawDataPackResponse.IndexOf("D([\"a\"", addressBlockStart);
// Fix by Billy Roebuck [billyroebuck@yahoo.com.au]; 6/24/2005
addressBlockStart = this._rawDataPackResponse.IndexOf("D([\"cl\",", addressBlockStart);
} ;
}
return;
}
///
/// Retrieves all the frequently mailed contacts in the user's Gmail address book.
///
///A of frequently mailed contacts in address book.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
// Can be used in place of GetContacts if you don't care about all the contacts.
public GmailContactCollection GetFrequentlyMailedContacts()
{
// instantiate output vars
GmailContactCollection output = new GmailContactCollection();
Uri location = new Uri(GMAIL_HOST_URL + "/mail?&ik=" + System.Web.HttpUtility.UrlEncode(this._session.IdentificationKey) + "&view=cl&search=contacts&pnl=d&zx=" + MakeUniqueUrl());
this._rawDataPackResponse = MakeWebRequest(location, "GET", null, null, true);
// sanitize the incoming _rawDataPackResponse
this._rawDataPackResponse = this._rawDataPackResponse.Replace("\n", "");
if (this._rawDataPackResponse.Length > 128)
{
// find the beginning of the address block
//int addressBlockStart = this._rawDataPackResponse.IndexOf("D([\"a\"");
// Fix by Billy Roebuck [billyroebuck@yahoo.com.au]; 6/24/2005
int addressBlockStart = this._rawDataPackResponse.IndexOf("D([\"cl\",");
// make multiple passes to parse all address arrays
while (addressBlockStart > -1)
{
// find the address block beginning and end
addressBlockStart = this._rawDataPackResponse.IndexOf("[", addressBlockStart + 8);
int addressBlockEnd = this._rawDataPackResponse.IndexOf("]]);", addressBlockStart) + 2;
// get the address block
string addressBlock = this._rawDataPackResponse.Substring(addressBlockStart, addressBlockEnd - addressBlockStart);
// parse the address block into an ArrayList
ArrayList addresses = Utilities.ParseJSArray(addressBlock);
// loop through ArrayList of contacts and insert into collection
foreach (ArrayList contact in addresses)
{
GmailContact currentContact = new GmailContact();
currentContact.id = int.Parse((string)contact[0], System.Globalization.NumberStyles.HexNumber);
GmailContact tmpContact = new GmailContact();
tmpContact.id = int.Parse((string)contact[0], System.Globalization.NumberStyles.HexNumber);
tmpContact.Email = contact[3].ToString();
tmpContact.Name = contact[1].ToString();
if (contact.Count > 4)
{
tmpContact.Notes = contact[4].ToString();
}
// to keep backwards compatibility with 0.6.1 and before
tmpContact.EmailUnescaped = System.Web.HttpUtility.HtmlEncode(contact[3].ToString());
tmpContact.IsFrequentlyMailed = true;
output.Add(tmpContact);
}
// Check to see if there is another block of contacts.
//addressBlockStart = this._rawDataPackResponse.IndexOf("D([\"a\"", addressBlockStart);
// Fix by Billy Roebuck [billyroebuck@yahoo.com.au]; 6/24/2005
addressBlockStart = this._rawDataPackResponse.IndexOf("D([\"cl\",", addressBlockStart);
} ;
}
return output;
}
///
/// Adds a contact into the address book. Emails that already exist will be updated with the new information.
///
/// Contact display name.
/// Contact email address.
/// Optional notes.
///True if Gmail accepted the command; false otherwise.
public bool AddContact(string name, string email, string notes)
{
// Limit labels to the 100 characters.
// Not sure if 100 is correct, I need to test actual limit.
if (name.Length > 100) name = name.Substring(0, 100);
if (email.Length > 100) email = email.Substring(0, 100);
string contactPostData = "act=ec"
+ "&at=" + this._session.Cookies["GMAIL_AT"].Value
+ "&ct_id=-1"
+ "&ct_nm=" + HttpUtility.UrlEncode(name)
+ "&ct_em=" + HttpUtility.UrlEncode(email)
+ "&ctf_n=" + HttpUtility.UrlEncode(notes);
Uri location = new Uri(GMAIL_CONTACT_URL);
this._rawDataPackResponse = MakeWebRequest(location, "POST", GMAIL_CONTACT_REFERRER_URL, contactPostData, false);
// Parse the data pack to determine if contact was stored successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
ParseDataPack();
// Return Gmail's response to whether the request was successful.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
return this.CommandSuccess;
}
///
/// Edits a contact in the address book.
///
/// ID of the contact on Gmail system.
/// Contact display name.
/// Contact email address.
/// Optional notes.
///True if Gmail accepted the command; false otherwise.
/// // Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public bool EditContact(int id, string name, string email, string notes)
{
if (id > -1)
{
string contactPostData = "act=ec"
+ "&at=" + this._session.Cookies["GMAIL_AT"].Value
+ "&ct_id=" + id
+ "&ct_nm=" + System.Web.HttpUtility.UrlEncode(name)
+ "&ct_em=" + System.Web.HttpUtility.UrlEncode(email)
+ "&ctf_n=" + System.Web.HttpUtility.UrlEncode(notes);
Uri location = new Uri(GMAIL_CONTACT_URL);
this._rawDataPackResponse = MakeWebRequest(location, "POST", GMAIL_LABEL_REFERRER_URL, contactPostData, false);
// Parse the data pack to determine if contact was edited successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
ParseDataPack();
// Return Gmail's response to whether the request was successful.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
return this.CommandSuccess;
}
else
return false;
}
///
/// Edits a contact in the address book.
///
/// Email of the contact as it is on Gmail.
/// Contact display name.
/// Contact email address.
/// Optional notes.
///True if Gmail accepted the command; false otherwise.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public bool EditContact(string oldEmail, string name, string email, string notes)
{
// loop through contacts to find the old email address
foreach (GmailContact contact in this._session.Contacts)
{
if (oldEmail == contact.Email)
{
// if Gmail provided an ID for this contact, pass it off to other EditContact function
if (contact.id > -1)
return EditContact(contact.id, name, email, notes);
else
return false;
}
}
return false;
}
///
/// Delete a contact from the address book.
///
/// ID of the contact to delete.
///True if Gmail accepted the command; false otherwise.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public bool DeleteContact(int id)
{
if (id > -1)
{
string contactGetData = "&ik=" + this._session.IdentificationKey
+ "&search=contacts"
+ "&ct_id=" + Convert.ToString(id, 16)
+ "&cvm=2"
+ "&view=up"
+ "&act=dc"
+ "&at=" + this._session.Cookies["GMAIL_AT"].Value
+ "&c=" + Convert.ToString(id, 16)
+ "&zx=" + MakeUniqueUrl();
Uri location = new Uri(GMAIL_CONTACT_DELETE_URL + contactGetData);
this._rawDataPackResponse = MakeWebRequest(location, "GET", GMAIL_LABEL_REFERRER_URL, null, false);
// Parse the data pack to determine if contact was deleted successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
ParseDataPack();
// Return Gmail's response to whether the request was successful.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
return this.CommandSuccess;
}
else
return false;
}
///
/// Delete a contact from the address book.
///
/// Email of the contact to delete.
///True if Gmail accepted the command; false otherwise.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public bool DeleteContact(string email)
{
foreach (GmailContact contact in this._session.Contacts)
{
if (email == contact.Email)
{
if (contact.id > -1)
return DeleteContact(contact.id);
else
return false;
}
}
return false;
}
#endregion
#region Filters
///
/// Retrieves all the filters in the user's Gmail account.
///
///A of filters.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public GmailFilterCollection GetFilters()
{
// instantiate output vars
GmailFilterCollection output = new GmailFilterCollection();
Uri location = new Uri(GMAIL_HOST_URL + "/mail?&ik=" + System.Web.HttpUtility.UrlEncode(this._session.IdentificationKey) + "&view=pr&pnl=f&zx=" + MakeUniqueUrl());
this._rawDataPackResponse = MakeWebRequest(location, "GET", null, null, false);
// sanitize the incoming _rawDataPackResponse
this._rawDataPackResponse = this._rawDataPackResponse.Replace("\n", "");
if (this._rawDataPackResponse.Length > 128)
{
int filterBlockStart = this._rawDataPackResponse.IndexOf("D([\"fi\"");
if (filterBlockStart > -1)
{
// find the filter block
filterBlockStart = this._rawDataPackResponse.IndexOf("[", filterBlockStart + 7);
int filterBlockEnd = this._rawDataPackResponse.IndexOf("]]);", filterBlockStart) + 1;
string filterBlock = this._rawDataPackResponse.Substring(filterBlockStart, filterBlockEnd - filterBlockStart);
// parse the filter block into an ArrayList
ArrayList filters = Utilities.ParseJSArray(filterBlock);
// loop through ArrayList of Filters and insert into collection
foreach (ArrayList Filter in filters)
{
// Using GmailFilter Indeces enum for easy changing
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
GmailFilter tmpFilter = new GmailFilter();
tmpFilter.id = Int64.Parse((string)Filter[(int)GmailFilter.Indeces.id]);
tmpFilter.Name = (string)Filter[(int)GmailFilter.Indeces.Name];
// Get subarray of filter settings
ArrayList tmpArray = (ArrayList)Filter[(int)GmailFilter.Indeces.SubArray];
tmpFilter.From = (string)tmpArray[(int)GmailFilter.SubIndeces.From];
tmpFilter.To = (string)tmpArray[(int)GmailFilter.SubIndeces.To];
tmpFilter.Subject = (string)tmpArray[(int)GmailFilter.SubIndeces.Subject];
tmpFilter.HasWords = (string)tmpArray[(int)GmailFilter.SubIndeces.HasWords];
tmpFilter.DoesntHave = (string)tmpArray[(int)GmailFilter.SubIndeces.DoesntHave];
tmpFilter.HasAttachment = tmpArray[(int)GmailFilter.SubIndeces.HasAttachment].ToString().Length > 0 && bool.Parse((string)tmpArray[(int)GmailFilter.SubIndeces.HasAttachment]);
tmpFilter.SkipInbox = tmpArray[(int)GmailFilter.SubIndeces.SkipInbox].ToString().Length > 0 && bool.Parse((string)tmpArray[(int)GmailFilter.SubIndeces.SkipInbox]);
tmpFilter.StarIt = tmpArray[(int)GmailFilter.SubIndeces.StarIt].ToString().Length > 0 && bool.Parse((string)tmpArray[(int)GmailFilter.SubIndeces.StarIt]);
tmpFilter.ApplyLabel = tmpArray[(int)GmailFilter.SubIndeces.ApplayLabel].ToString().Length > 0 && bool.Parse((string)tmpArray[(int)GmailFilter.SubIndeces.ApplayLabel]);
tmpFilter.LabelToApply = (string)tmpArray[(int)GmailFilter.SubIndeces.LabelToApply];
tmpFilter.Forward = tmpArray[(int)GmailFilter.SubIndeces.Forward].ToString().Length > 0 && bool.Parse((string)tmpArray[(int)GmailFilter.SubIndeces.Forward]);
tmpFilter.ForwardTo = (string)tmpArray[(int)GmailFilter.SubIndeces.ForwardTo];
tmpFilter.MoveToTrash = tmpArray[(int)GmailFilter.SubIndeces.MoveToTrash].ToString().Length > 0 && bool.Parse((string)tmpArray[(int)GmailFilter.SubIndeces.MoveToTrash]);
// I'm not sure why the following fields are sent twice.
// If Gmail changes the filter format, these may need to be used.
//Filter[GmailFilter.Indeces.StarIt] = StarIt
//Filter[GmailFilter.Indeces.LabelToApply] = LabelToApply
//Filter[GmailFilter.Indeces.MoveToTrash] = Move To Trash
//Filter[GmailFilter.Indeces.MoveToTrash2] = Move To Trash
//Filter[GmailFilter.Indeces.ForwardTo] = ForwardTo
//Filter[GmailFilter.Indeces.PerpetualFalse] = always seems to be false
output.Add(tmpFilter);
}
}
}
return output;
}
///
/// Adds a filter into the set of Gmail filters.
///
///A true if completed successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public bool AddFilter(GmailFilter filter)
{
string strLocation = GMAIL_FILTER_URL
+ "&ik=" + this._session.IdentificationKey
+ "&view=pr"
+ "&pnl=f"
+ "&at=" + this._session.Cookies["GMAIL_AT"].Value
+ "&act=cf"
+ "&cf_t=cf"
+ "&cf1_from=" + System.Web.HttpUtility.UrlEncode(filter.From)
+ "&cf1_to=" + System.Web.HttpUtility.UrlEncode(filter.To)
+ "&cf1_subj=" + System.Web.HttpUtility.UrlEncode(filter.Subject)
+ "&cf1_has=" + System.Web.HttpUtility.UrlEncode(filter.HasWords)
+ "&cf1_hasnot=" + System.Web.HttpUtility.UrlEncode(filter.DoesntHave)
+ "&cf1_attach=" + System.Web.HttpUtility.UrlEncode(filter.HasAttachment.ToString().ToLower())
+ "&cf2_ar=" + System.Web.HttpUtility.UrlEncode(filter.SkipInbox.ToString().ToLower())
+ "&cf2_st=" + System.Web.HttpUtility.UrlEncode(filter.StarIt.ToString().ToLower())
+ "&cf2_cat=" + System.Web.HttpUtility.UrlEncode(filter.ApplyLabel.ToString().ToLower())
+ "&cf2_sel=" + System.Web.HttpUtility.UrlEncode(filter.LabelToApply)
+ "&cf2_emc=" + System.Web.HttpUtility.UrlEncode(filter.Forward.ToString().ToLower())
+ "&cf2_email=" + System.Web.HttpUtility.UrlEncode(filter.ForwardTo)
+ "&cf2_tr=" + System.Web.HttpUtility.UrlEncode(filter.MoveToTrash.ToString().ToLower())
+ "&zx=" + MakeUniqueUrl();
Uri location = new Uri(strLocation);
string referrer = GMAIL_FILTER_REFERRER_URL
+ "&pnl=f"
+ "&ik=" + this._session.IdentificationKey
+ "&search=cf"
+ "&view=tl"
+ "&start=0"
+ "&cf_f=cf1"
+ "&cf_t=cf2"
+ "&cf1_from=" + System.Web.HttpUtility.UrlEncode(filter.From)
+ "&cf1_to=" + System.Web.HttpUtility.UrlEncode(filter.To)
+ "&cf1_subj=" + System.Web.HttpUtility.UrlEncode(filter.Subject)
+ "&cf1_has=" + System.Web.HttpUtility.UrlEncode(filter.HasWords)
+ "&cf1_hasnot=" + System.Web.HttpUtility.UrlEncode(filter.DoesntHave)
+ "&cf1_attach=" + System.Web.HttpUtility.UrlEncode(filter.HasAttachment.ToString().ToLower())
+ "&zx=" + MakeUniqueUrl();
this._rawDataPackResponse = MakeWebRequest(location, "GET", referrer, string.Empty, false);
// Parse the data pack to determine if filter was stored successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
ParseDataPack();
// Return Gmail's response to whether the request was successful.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
return this.CommandSuccess;
}
///
/// Edits a filter into the set of Gmail filters.
///
///A true if completed successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public bool EditFilter(GmailFilter filter)
{
string strLocation = GMAIL_FILTER_URL
+ "&ik=" + this._session.IdentificationKey
+ "&view=pr"
+ "&pnl=f"
+ "&at=" + this._session.Cookies["GMAIL_AT"].Value
+ "&act=rf"
+ "&cf_t=rf"
+ "&cf1_from=" + System.Web.HttpUtility.UrlEncode(filter.From)
+ "&cf1_to=" + System.Web.HttpUtility.UrlEncode(filter.To)
+ "&cf1_subj=" + System.Web.HttpUtility.UrlEncode(filter.Subject)
+ "&cf1_has=" + System.Web.HttpUtility.UrlEncode(filter.HasWords)
+ "&cf1_hasnot=" + System.Web.HttpUtility.UrlEncode(filter.DoesntHave)
+ "&cf1_attach=" + System.Web.HttpUtility.UrlEncode(filter.HasAttachment.ToString().ToLower())
+ "&cf2_ar=" + System.Web.HttpUtility.UrlEncode(filter.SkipInbox.ToString().ToLower())
+ "&cf2_st=" + System.Web.HttpUtility.UrlEncode(filter.StarIt.ToString().ToLower())
+ "&cf2_cat=" + System.Web.HttpUtility.UrlEncode(filter.ApplyLabel.ToString().ToLower())
+ "&cf2_sel=" + System.Web.HttpUtility.UrlEncode(filter.LabelToApply)
+ "&cf2_emc=" + System.Web.HttpUtility.UrlEncode(filter.Forward.ToString().ToLower())
+ "&cf2_email=" + System.Web.HttpUtility.UrlEncode(filter.ForwardTo)
+ "&cf2_tr=" + System.Web.HttpUtility.UrlEncode(filter.MoveToTrash.ToString().ToLower())
+ "&ofid=" + System.Web.HttpUtility.UrlEncode(filter.id.ToString())
+ "&zx=" + MakeUniqueUrl();
Uri location = new Uri(strLocation);
string referrer = GMAIL_FILTER_REFERRER_URL
+ "&ik=" + this._session.IdentificationKey
+ "&search=cf"
+ "&view=tl"
+ "&start=0"
+ "&cf_f=cf1"
+ "&cf_t=cf2"
+ "&cf1_from=" + System.Web.HttpUtility.UrlEncode(filter.From)
+ "&cf1_to=" + System.Web.HttpUtility.UrlEncode(filter.To)
+ "&cf1_subj=" + System.Web.HttpUtility.UrlEncode(filter.Subject)
+ "&cf1_has=" + System.Web.HttpUtility.UrlEncode(filter.HasWords)
+ "&cf1_hasnot=" + System.Web.HttpUtility.UrlEncode(filter.DoesntHave)
+ "&cf1_attach=" + System.Web.HttpUtility.UrlEncode(filter.HasAttachment.ToString().ToLower())
+ "&cf2_ar=" + System.Web.HttpUtility.UrlEncode(filter.SkipInbox.ToString().ToLower())
+ "&cf2_st=" + System.Web.HttpUtility.UrlEncode(filter.StarIt.ToString().ToLower())
+ "&cf2_cat=" + System.Web.HttpUtility.UrlEncode(filter.ApplyLabel.ToString().ToLower())
+ "&cf2_sel=" + System.Web.HttpUtility.UrlEncode(filter.LabelToApply)
+ "&cf2_emc=" + System.Web.HttpUtility.UrlEncode(filter.Forward.ToString().ToLower())
+ "&cf2_email=" + System.Web.HttpUtility.UrlEncode(filter.ForwardTo)
+ "&cf2_tr=" + System.Web.HttpUtility.UrlEncode(filter.MoveToTrash.ToString().ToLower())
+ "&ofid=" + System.Web.HttpUtility.UrlEncode(filter.id.ToString())
+ "&zx=" + MakeUniqueUrl();
this._rawDataPackResponse = MakeWebRequest(location, "GET", referrer, string.Empty, false);
// Parse the data pack to determine if filter was edited successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
ParseDataPack();
// Return Gmail's response to whether the request was successful.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
return this.CommandSuccess;
}
///
/// Deletes a filter from the set of Gmail filters.
///
///A true if completed successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public bool DeleteFilter(Int64 id)
{
string labelPostData = "act=df_" + id.ToString() +
"&at=" + this._session.Cookies["GMAIL_AT"].Value;
Uri location = new Uri(GMAIL_FILTER_URL + "&ik=&view=up");
string referrer = GMAIL_FILTER_REFERRER_URL + "&view=pr&ik= " + this._session.IdentificationKey + "&zx=" + MakeUniqueUrl();
this._rawDataPackResponse = MakeWebRequest(location, "POST", referrer, labelPostData, false);
// Parse the data pack to determine if filter was deleted successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
ParseDataPack();
// Return Gmail's response to whether the request was successful.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
return this.CommandSuccess;
}
///
/// Deletes a filter from the set of Gmail filters.
///
///A true if completed successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public bool DeleteFilter(GmailFilter filter)
{
return DeleteFilter(filter.id);
}
#endregion
#region Labels
///
/// Adds a label to the set of Gmail labels.
///
///A true if completed successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public bool AddLabel(string label)
{
// Limit labels to the 100 characters.
// Not sure if 100 is correct, I need to test actual limit.
if (label.Length > 100) label = label.Substring(0, 100);
string labelPostData = "act=cc_" + System.Web.HttpUtility.UrlEncode(label) +
"&at=" + this._session.Cookies["GMAIL_AT"].Value;
Uri location = new Uri(GMAIL_LABEL_URL);
string referrer = GMAIL_LABEL_REFERRER_URL + "&ik= " + this._session.IdentificationKey + "&zx=" + MakeUniqueUrl();
this._rawDataPackResponse = MakeWebRequest(location, "POST", referrer, labelPostData, false);
// Parse the data pack to determine if label was stored successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
ParseDataPack();
// Return Gmail's response to whether the request was successful.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
return this.CommandSuccess;
}
///
/// Delete a label from the set of Gmail labels.
///
///A true if completed successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public bool DeleteLabel(string label)
{
// Limit labels to the 100 characters.
// Not sure if 100 is correct, I need to test actual limit.
if (label.Length > 100) label = label.Substring(0, 100);
string labelPostData = "act=dc_" + System.Web.HttpUtility.UrlEncode(label) +
"&at=" + this._session.Cookies["GMAIL_AT"].Value;
Uri location = new Uri(GMAIL_LABEL_URL);
string referrer = GMAIL_LABEL_REFERRER_URL + "&ik= " + this._session.IdentificationKey + "&zx=" + MakeUniqueUrl();
this._rawDataPackResponse = MakeWebRequest(location, "POST", referrer, labelPostData, false);
// Parse the data pack to determine if label was deleted successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
ParseDataPack();
// Return Gmail's response to whether the request was successful.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
return this.CommandSuccess;
}
///
/// Rename a label in the set of Gmail labels.
///
///A true if completed successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public bool RenameLabel(string oldName, string newName)
{
// Limit labels to the 100 characters.
// Not sure if 100 is correct, I need to test actual limit.
if (oldName.Length > 100) oldName = oldName.Substring(0, 100);
if (newName.Length > 100) newName = newName.Substring(0, 100);
string labelPostData = "act=nc_" + System.Web.HttpUtility.UrlEncode(oldName + "^" + newName) +
"&at=" + this._session.Cookies["GMAIL_AT"].Value;
Uri location = new Uri(GMAIL_LABEL_URL);
string referrer = GMAIL_LABEL_REFERRER_URL + "&ik= " + this._session.IdentificationKey + "&zx=" + MakeUniqueUrl();
this._rawDataPackResponse = MakeWebRequest(location, "POST", referrer, labelPostData, false);
// Parse the data pack to determine if label was renamed successfully.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
ParseDataPack();
// Return Gmail's response to whether the request was successful.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
return this.CommandSuccess;
}
#endregion
#region Invites
///
/// Send a Gmail invite to an email address.
///
/// Email of the receipient of the invite.
///True if Gmail accepted the command; false otherwise.
// This may be useless after beta stages.
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
public bool SendInvite(string email)
{
string invitePostData = "act=ii"
+ "&at=" + this._session.Cookies["GMAIL_AT"].Value
+ "&em=" + System.Web.HttpUtility.UrlEncode(email);
Uri location = new Uri(GMAIL_INVITE_URL + "&ik=" + this._session.IdentificationKey);
this._rawDataPackResponse = MakeWebRequest(location, "POST", GMAIL_INVITE_REFERRER_URL, invitePostData, false);
// Parse the data pack to determine if invite was sent.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
ParseDataPack();
// Return Gmail's response to whether the request was successful.
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
return this.CommandSuccess;
}
#endregion
#region Communication and Parsing
///
/// Reads in the DataPack and extracts relevant mailbox data.
///
private void ParseDataPack()
{
// sanitize the incoming _rawDataPackResponse
_rawDataPackResponse = _rawDataPackResponse.Replace("\n", "");
_rawDataPackResponse = _rawDataPackResponse.Replace("D([", "\nD([");
_rawDataPackResponse = _rawDataPackResponse.Replace("]);", "]);\n");
// extract the fingerprint, i.e. var fp='6c8abc683047b5bc'
Match fp = Regex.Match(this._rawDataPackResponse, "var fp='([A-Za-z0-9]+)'", RegexOptions.Compiled);
if (fp.Success)
{
this._session.Fingerprint = fp.Groups[1].Value;
// clear internal thread store
this._session.UnreadThreads.Clear();
}
else
{
Debug.WriteLine("DataPack error: Could not find the DataPack fingerprint.");
}
// capture all the dataItems
Regex r = new Regex(@"D\((?\[.+\])\)", RegexOptions.ExplicitCapture | RegexOptions.Compiled);
Match m = r.Match(_rawDataPackResponse);
// loop through all the dataItems and insert accordingly
while (m.Success)
{
// get ArrayList version of dataPack JS array
ArrayList tmpArray = Utilities.ParseJSArray(m.Groups[1].Value);
// get name of DataItem
string settingName = (string)tmpArray[0];
// strip the name element; reindexes the array
tmpArray.RemoveAt(0);
SortedList sl;
switch (settingName)
{
case "a":
Debug.WriteLine("Test");
break;
case "ds": // default searches
if (tmpArray.Count == 7)
{
sl = this._session.DefaultSearchCounts;
sl["Inbox"] = Int32.Parse((string)tmpArray[0]);
sl["Starred"] = Int32.Parse((string)tmpArray[1]);
sl["Sent"] = Int32.Parse((string)tmpArray[2]);
sl["Drafts"] = Int32.Parse((string)tmpArray[3]); // fix by Brian Hampson [brian.hampson@gmail.com]; 10/6/2004
sl["All"] = Int32.Parse((string)tmpArray[4]);
sl["Spam"] = Int32.Parse((string)tmpArray[5]);
sl["Trash"] = Int32.Parse((string)tmpArray[6]);
}
else
{
Debug.WriteLine("DataPack error: 'ds' did not have expected number of elements (6).");
}
break;
case "ct": // categories
sl = this._session.CategoryCounts;
foreach (ArrayList sub in (ArrayList)tmpArray[0])
{
sl[(string)sub[0]] = Int32.Parse((string)sub[1]);
}
break;
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
case "ar": // Check Gmail's success/failure response
if (tmpArray.Count == 3)
{
this.CommandSuccess = Int32.Parse(tmpArray[0].ToString()) == 1;
this.CommandResponse = tmpArray[1].ToString();
}
break;
case "ts": // threadlist summary
if (tmpArray.Count == 9)
{
this._session.ThreadListTimestamp = tmpArray[6].ToString();
this._session.TotalMessages = Int32.Parse(tmpArray[2].ToString());
}
else
{
Debug.WriteLine("DataPack error: 'ts' did not have expected number of elements (7).");
}
break;
case "qu": // quota information
this._session.Quota = int.Parse(((string)tmpArray[1]).Substring(0, tmpArray[1].ToString().Length - 3));
this._session.MailboxSize = int.Parse(((string)tmpArray[0]).Substring(0, tmpArray[0].ToString().Length -3));
break;
case "fi": // filters
break;
case "t": // message listings *** NOTE: If Gmail changes their spec, this will definitely need to be updated. ***
foreach (ArrayList message in tmpArray)
{
// Using GmailThread Indeces enum for easy changing
// Added by Eric Larson [larson.eric@gmail.com]; 5/10/2005
// we really only want the unread messages
if ((string)message[(int)GmailThread.Indeces.IsRead] == "1")
{
GmailThread newMessage = new GmailThread();
newMessage.ThreadID = (string)message[(int)GmailThread.Indeces.ID];
newMessage.IsRead = ((string)message[(int)GmailThread.Indeces.IsRead] == "1" ? false : true); // Gmail reports isUnread, so we swap
newMessage.IsStarred = ((string)message[(int)GmailThread.Indeces.IsStarred] == "1" ? true : false);
newMessage.DateHtml = (string)message[(int)GmailThread.Indeces.DateHtml];
newMessage.AuthorsHtml = (string)message[(int)GmailThread.Indeces.AuthorsHtml];
newMessage.Flags = (string)message[(int)GmailThread.Indeces.Flags];
newMessage.SubjectHtml = (string)message[(int)GmailThread.Indeces.SubjectHtml];
newMessage.SnippetHtml = (string)message[(int)GmailThread.Indeces.SnippetHtml];
newMessage.Categories = (ArrayList)message[(int)GmailThread.Indeces.Categories];
newMessage.AttachHtml = (string)message[(int)GmailThread.Indeces.AttachHtml];
newMessage.MatchingMessageID = (string)message[(int)GmailThread.Indeces.MatchingMessageID];
this._session.UnreadThreads.Add(newMessage);
}
}
break;
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
case "ud": // IK value. What's IK stand for? Anyone?
this._session.IdentificationKey = (string)tmpArray[2];
break;
// Added by Eric Larson [larson.eric@gmail.com]; 5/2/2005
case "i": // invitations
this._session.Invites.Count = int.Parse((string)tmpArray[0]);
break;
default:
break;
}
// advance to next dataItem
m = m.NextMatch();
}
this._session.FinalizeUpdate();
}
///
/// Attempts an HTTP request and returns the response document.
///
/// Resource to request.
/// "GET" or "POST".
/// The HTTP referer (it's spelled 'referrer', dammit!).
/// If method if POST, pass the request document; null otherwise.
/// Set to true to allow client to follow redirect.
///
private string MakeWebRequest(Uri location, string method, string referrer, string postData, bool allowAutoRedirect)
{
Debug.WriteLine("Initiating " + method + " request at: " + location.ToString());
// reset last request's success response
// Added by Eric larson [larson.eric@gmail.com]; 5/10/2005
this.CommandResponse = string.Empty;
this.CommandSuccess = false;
// prepare HTTP request
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(location);
// enable proxy support if the user has specified it, or init an empty one
// Fix from Brian Hampson [brian.hampson@gmail.com]; 10/6/2004
if (this._proxy != null)
{
webRequest.Proxy = this._proxy;
}
else
{
webRequest.Proxy = GlobalProxySelection.GetEmptyWebProxy();
}
// if POSTing, add request page and modify the headers
byte[] encodedPostData = new byte[0];
if (method == "POST")
{
ASCIIEncoding encoding = new ASCIIEncoding();
encodedPostData = encoding.GetBytes(postData);
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ContentLength = encodedPostData.Length;
}
else
{
webRequest.Method = "GET";
webRequest.ContentType = "text/html";
}
webRequest.Headers["Accept-Language"] = "en-us,en;q=0.5";
webRequest.Headers["Accept-Charset"] = "ISO-8859-1,utf-8;q=0.7,*;q=0.7";
webRequest.ProtocolVersion = HttpVersion.Version11;
webRequest.AllowAutoRedirect = allowAutoRedirect;
webRequest.KeepAlive = true;
webRequest.Referer = referrer;
webRequest.CookieContainer = new CookieContainer();
// adding cookies one-by-one because certain cookies were being added
// that did not fit the uri path
// Fix from Eric Larson [larson.eric@gmail.com]; 4/21/2005
//webRequest.CookieContainer.Add(location, this._session.Cookies);
foreach (Cookie tmpCookie in this._session.Cookies)
{
if ((location.Host.IndexOf(tmpCookie.Domain) > -1) && (location.AbsolutePath.IndexOf(tmpCookie.Path) > -1))
{
Debug.WriteLine("Cookie: " + tmpCookie.Name + " " + tmpCookie.Value + " " + tmpCookie.Domain + " " + tmpCookie.Path);
webRequest.CookieContainer.Add(tmpCookie);
}
}
// updated UserAgent to the most recent version of Mozilla FireFox
// updated the Accept paramater to match the (my) latest version of Mozilla FireFox
// updated by Eric Larson [larson.eric@gmail.com]; 4/21/2005
webRequest.UserAgent = "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.7) Gecko/20050414 Firefox/1.0.3";
webRequest.Accept = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
// Attempt to send request stream to server if POSTing
if (method == "POST")
{
Stream requestStream = null;
try
{
requestStream = webRequest.GetRequestStream();
requestStream.Write(encodedPostData, 0, encodedPostData.Length);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
finally
{
if (requestStream != null)
{
requestStream.Close();
}
}
}
// Attempt to get response from server
HttpWebResponse webResponse = null;
string output = "";
try
{
// get response
webResponse = (HttpWebResponse)webRequest.GetResponse();
string headers = "";
foreach (string key in webResponse.Headers.Keys)
{
headers += key + "=" + webResponse.Headers[key] + " | ";
}
Debug.WriteLine(" Headers: " + headers);
// manually set the GV cookie because ASP.NET doesn't like the subdomain
if (webResponse.Headers["Set-Cookie"] != null)
{
int tmpCursor = webResponse.Headers["Set-Cookie"].IndexOf("GV=");
if (tmpCursor > -1)
{
int tmpEndCursor = webResponse.Headers["Set-Cookie"].IndexOf(";", tmpCursor);
string tmpVal = webResponse.Headers["Set-Cookie"].Substring(tmpCursor + 3, tmpEndCursor - tmpCursor - 3);
Debug.WriteLine(" Adding GV cookie: " + tmpVal);
Cookie tmpCookie = new Cookie("GV", tmpVal, "/", ".google.com");
this._session.Cookies.Add(tmpCookie);
}
}
// add new cookies to cookie jar
this._session.Cookies.Add(webResponse.Cookies);
foreach (Cookie ck in webResponse.Cookies)
{
Debug.WriteLine(" Adding cookie: " + ck.ToString());
}
// read response stream and dump to string
Stream streamResponse = webResponse.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
output = streamRead.ReadToEnd();
streamRead.Close();
streamResponse.Close();
// the initial login tries to redirect the browser to a temporarily moved page (HTTP 302)
// but if you set allowAutoRedirect = true, you receive an error about not being able to
// securely handshaking or something like that (I don't exactly remember)
// so if google tries to redirect the browser, form a new uri and make a new MakeWebRequest call
// Fix from Eric Larson [larson.eric@gmail.com]; 4/21/2005
if (webResponse.Headers["Location"] != null)
{
string redirect = webResponse.Headers["Location"];
Uri uriRedirect;
// if redirected to absolute uri
if (redirect.IndexOf("http") == 0)
{
uriRedirect = new Uri(redirect);
}
// if redirected to the current directory of the current uri
else if (redirect.IndexOf("/") != 0)
{
for (int i = location.Segments.GetLength(0) - 2; i >= 0; i--)
{
redirect = location.Segments[i] + redirect;
}
uriRedirect = new Uri(location.Scheme + "://" + location.Host + redirect);
}
// else if redirected to the root of the current uri's host
else
{
uriRedirect = new Uri(location.Scheme + "://" + location.Host + redirect);
}
// make recursive web request call
output = MakeWebRequest(uriRedirect, "GET", GOOGLE_LOGIN_REFERRER_URL, string.Empty, false);
}
Debug.WriteLine("Received response (" + output.Length + " char(s))");
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
finally
{
if (webResponse != null)
{
webResponse.Close();
}
}
// return the response document
return output;
}
///
/// Generates a proxy defeating random string (passed as the 'zx' GET variable).
///
///Random string composed of JS version and random string.
private string MakeUniqueUrl()
{
Random rnd = new Random();
// The significance of 2147483648 is that it's equal to 2^32, or 2GB.
return this._jsVersion + Convert.ToString((Math.Round(rnd.Next(1, 999) * 2147483.648)));
}
#endregion
}
}
When I'm using ASP.NET Repeater instead of I can't find EmptyDataTemplate like in GridView. I've implemented Repeater with Empty template.
using System.Collections;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Gnilly.Controls
{
public class EmptyRepeater : Repeater
{
private ITemplate _emptyTemplate;
public ITemplate EmptyTemplate
{
get { return _emptyTemplate; }
set { _emptyTemplate = value; }
}
protected override void CreateControlHierarchy( bool useDataSource )
{
IEnumerable data = GetData();
if ( EmptyTemplate != null && data != null && !data.GetEnumerator().MoveNext() )
{
WebControl control = new WebControl( HtmlTextWriterTag.Div );
EmptyTemplate.InstantiateIn( control );
Controls.Add( control );
}
else
{
base.CreateControlHierarchy( useDataSource );
}
}
}
}
Imports System
Imports System.Collections.Specialized
Imports System.Net
Imports System.Text
Imports System.Text.RegularExpressions
Imports MailContact
Imports System.Collections
Namespace Gnilly.Syndication.Mail
Public Class YahooExtract
Private Const _addressBookUrl As String = "http://address.yahoo.com/yab/us/Yahoo_ab.csv?loc=us&.rand=1671497644&A=H&Yahoo_ab.csv"
Private Const _authUrl As String = "https://login.yahoo.com/config/login?"
Private Const _loginPage As String = "https://login.yahoo.com/config/login"
Private Const _userAgent As String = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3"
Public Function Extract(ByVal uname As String, ByVal upass As String) As ArrayList
Dim result As Boolean = False
Dim myarray As New ArrayList
Try
Dim webClient As New WebClient()
webClient.Headers(HttpRequestHeader.UserAgent) = _userAgent
webClient.Encoding = Encoding.UTF8
Dim firstResponse As Byte() = webClient.DownloadData(_loginPage)
Dim firstRes As String = Encoding.UTF8.GetString(firstResponse)
Dim postToLogin As New NameValueCollection()
Dim regex As New Regex("type=""hidden"" name=""(.*?)"" value=""(.*?)""", RegexOptions.IgnoreCase)
Dim match As Match = regex.Match(firstRes)
While match.Success
If match.Groups(0).Value.Length > 0 Then
postToLogin.Add(match.Groups(1).Value, match.Groups(2).Value)
End If
match = regex.Match(firstRes, match.Index + match.Length)
End While
postToLogin.Add(".save", "Sign In")
postToLogin.Add(".persistent", "y")
'Dim login As String = credential.UserName.Split("@"c)(0)
Dim login As String = uname.Split("@")(0)
postToLogin.Add("login", login)
postToLogin.Add("passwd", upass)
webClient.Headers(HttpRequestHeader.UserAgent) = _userAgent
webClient.Headers(HttpRequestHeader.Referer) = _loginPage
webClient.Encoding = Encoding.UTF8
webClient.Headers(HttpRequestHeader.Cookie) = webClient.ResponseHeaders(HttpResponseHeader.SetCookie)
webClient.UploadValues(_authUrl, postToLogin)
Dim cookie As String = webClient.ResponseHeaders(HttpResponseHeader.SetCookie)
'If String.IsNullOrEmpty(cookie) Then
'Return False
'End If
Dim newCookie As String = String.Empty
Dim tmp1 As String() = cookie.Split(","c)
For Each var As String In tmp1
Dim tmp2 As String() = var.Split(";"c)
newCookie = IIf([String].IsNullOrEmpty(newCookie), tmp2(0), newCookie + ";" + tmp2(0))
Next
' set login cookie
webClient.Headers(HttpRequestHeader.Cookie) = newCookie
Dim thirdResponse As Byte() = webClient.DownloadData(_addressBookUrl)
Dim thirdRes As String = Encoding.UTF8.GetString(thirdResponse)
Dim crumb As String = String.Empty
Dim regexCrumb As New Regex("type=""hidden"" name=""\.crumb"" id=""crumb1"" value=""(.*?)""", RegexOptions.IgnoreCase)
match = regexCrumb.Match(thirdRes)
If match.Success AndAlso match.Groups(0).Value.Length > 0 Then
crumb = match.Groups(1).Value
End If
Dim postDataAB As New NameValueCollection()
postDataAB.Add(".crumb", crumb)
postDataAB.Add("vcp", "import_export")
postDataAB.Add("submit[action_export_yahoo]", "Export Now")
webClient.Headers(HttpRequestHeader.UserAgent) = _userAgent
webClient.Headers(HttpRequestHeader.Referer) = _addressBookUrl
Dim FourResponse As Byte() = webClient.UploadValues(_addressBookUrl, postDataAB)
Dim csvData As String = Encoding.UTF8.GetString(FourResponse)
Dim lines As String() = csvData.Split(Chr(10))
'Dim list1 As Hashtable()
For Each line As String In lines
Dim items As String() = line.Split(","c)
If items.Length < 5 Then
Continue For
End If
Dim email As String = items(4)
Dim name As String = items(3)
If Not String.IsNullOrEmpty(email) AndAlso Not String.IsNullOrEmpty(name) Then
email = email.Trim(""""c)
name = name.Trim(""""c)
If Not email.Equals("Email") AndAlso Not name.Equals("Nickname") Then
Dim mailContact As New MailContact()
mailContact.Name = name
mailContact.Email = email
myarray.Add(email)
'list.Add(mailContact)
End If
End If
Next
result = True
Catch
End Try
Return myarray
End Function
End Class
End Namespace
Public Class MailContact
Private _email As String = String.Empty
Private _name As String = String.Empty
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
Public Property Email() As String
Get
Return _email
End Get
Set(ByVal value As String)
_email = value
End Set
End Property
Public ReadOnly Property FullEmail() As String
Get
Return Email
End Get
End Property
End Class
I tried to find free Yahoo! Contact import code for .NET platform. I found only paid packages for 300+$.
I've implemented importing and you can use it for free.
(But you need to make some change in code to compile it)
using System;
using System.Collections.Specialized;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
namespace Gnilly.Syndication.Mail
{
public class YahooExtract
{
private const string _addressBookUrl = "http://address.yahoo.com/yab/us/Yahoo_ab.csv?loc=us&.rand=1671497644&A=H&Yahoo_ab.csv";
private const string _authUrl = "https://login.yahoo.com/config/login?";
private const string _loginPage = "https://login.yahoo.com/config/login";
private const string _userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3";
public bool Extract( NetworkCredential credential, out MailContactList list )
{
bool result = false;
list = new MailContactList();
try
{
WebClient webClient = new WebClient();
webClient.Headers[ HttpRequestHeader.UserAgent ] = _userAgent;
webClient.Encoding = Encoding.UTF8;
byte[] firstResponse = webClient.DownloadData( _loginPage );
string firstRes = Encoding.UTF8.GetString( firstResponse );
NameValueCollection postToLogin = new NameValueCollection();
Regex regex = new Regex( "type=\"hidden\" name=\"(.*?)\" value=\"(.*?)\"", RegexOptions.IgnoreCase );
Match match = regex.Match( firstRes );
while ( match.Success )
{
if ( match.Groups[ 0 ].Value.Length > 0 )
{
postToLogin.Add( match.Groups[ 1 ].Value, match.Groups[ 2 ].Value );
}
match = regex.Match( firstRes, match.Index + match.Length );
}
postToLogin.Add( ".save", "Sign In" );
postToLogin.Add( ".persistent", "y" );
string login = credential.UserName.Split( '@' )[ 0 ];
postToLogin.Add( "login", login );
postToLogin.Add( "passwd", credential.Password );
webClient.Headers[ HttpRequestHeader.UserAgent ] = _userAgent;
webClient.Headers[ HttpRequestHeader.Referer ] = _loginPage;
webClient.Encoding = Encoding.UTF8;
webClient.Headers[ HttpRequestHeader.Cookie ] = webClient.ResponseHeaders[ HttpResponseHeader.SetCookie ];
webClient.UploadValues( _authUrl, postToLogin );
string cookie = webClient.ResponseHeaders[ HttpResponseHeader.SetCookie ];
if ( string.IsNullOrEmpty( cookie ) )
{
return false;
}
string newCookie = string.Empty;
string[] tmp1 = cookie.Split( ',' );
foreach ( string var in tmp1 )
{
string[] tmp2 = var.Split( ';' );
newCookie = String.IsNullOrEmpty( newCookie ) ? tmp2[ 0 ] : newCookie + ";" + tmp2[ 0 ];
}
// set login cookie
webClient.Headers[ HttpRequestHeader.Cookie ] = newCookie;
byte[] thirdResponse = webClient.DownloadData( _addressBookUrl );
string thirdRes = Encoding.UTF8.GetString( thirdResponse );
string crumb = string.Empty;
Regex regexCrumb = new Regex( "type=\"hidden\" name=\"\\.crumb\" id=\"crumb1\" value=\"(.*?)\"", RegexOptions.IgnoreCase );
match = regexCrumb.Match( thirdRes );
if ( match.Success && match.Groups[ 0 ].Value.Length > 0 )
{
crumb = match.Groups[ 1 ].Value;
}
NameValueCollection postDataAB = new NameValueCollection();
postDataAB.Add( ".crumb", crumb );
postDataAB.Add( "vcp", "import_export" );
postDataAB.Add( "submit[action_export_yahoo]", "Export Now" );
webClient.Headers[ HttpRequestHeader.UserAgent ] = _userAgent;
webClient.Headers[ HttpRequestHeader.Referer ] = _addressBookUrl;
byte[] FourResponse = webClient.UploadValues( _addressBookUrl, postDataAB );
string csvData = Encoding.UTF8.GetString( FourResponse );
string[] lines = csvData.Split( '\n' );
foreach ( string line in lines )
{
string[] items = line.Split( ',' );
if ( items.Length < 5 )
{
continue;
}
string email = items[ 4 ];
string name = items[ 3 ];
if ( !string.IsNullOrEmpty( email ) && !string.IsNullOrEmpty( name ) )
{
email = email.Trim( '\"' );
name = name.Trim( '\"' );
if ( !email.Equals( "Email" ) && !name.Equals( "Nickname" ) )
{
MailContact mailContact = new MailContact();
mailContact.Name = name;
mailContact.Email = email;
list.Add( mailContact );
}
}
}
result = true;
}
catch
{
}
return result;
}
}
}