Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.IO;
- using System.Text;
- using System.Net.Sockets;
- using System.Collections.Generic;
- using System.Net.Security;
- using GmailViewer.Email.Folders;
- using GmailViewer.Email.Message;
- using GmailViewer.Email.Body;
- namespace GmailViewer.Email
- {
- public delegate void GmailEvent<T>(GmailClient Client, T Parameter);
- public enum GmailState
- {
- Closed,
- Connected,
- Authorized,
- Selected
- }
- public class GmailClient
- {
- private string Username;
- private string Password;
- private int CurrentCommand;
- private StreamReader Reader;
- private Socket Connection;
- private SslStream Stream;
- private GmailState State;
- public GmailEvent<object> OnLogin;
- public GmailEvent<object> OnLogout;
- public GmailEvent<string> OnError;
- public GmailClient(string Username, string Password)
- {
- this.CurrentCommand = 0;
- this.Username = Username;
- this.Password = Password;
- this.State = GmailState.Closed;
- this.Connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- }
- public bool Connected()
- {
- return (State != GmailState.Closed);
- }
- public void Login()
- {
- if (State == GmailState.Closed)
- {
- Connection.BeginConnect("imap.gmail.com", 993, new AsyncCallback(ConnectionEstablished), this);
- }
- else
- {
- if (OnError != null)
- OnError.Invoke(this, "State != GmailState.Closed");
- }
- }
- private void ConnectionEstablished(IAsyncResult Result)
- {
- try
- {
- State = GmailState.Connected;
- Stream = new SslStream(new NetworkStream(Connection));
- Stream.AuthenticateAsClient("imap.gmail.com");
- Reader = new StreamReader(Stream, Encoding.ASCII);
- Authenticate();
- }
- catch (Exception Error)
- {
- if (OnError != null)
- OnError.Invoke(this, Error.ToString());
- }
- }
- private void Authenticate()
- {
- string Response;
- if (ValidResponse(Response = ReadLine()))
- {
- ExecuteCommand("CAPABILITY");
- if (ValidResponse(Response = ReadMultiline()))
- {
- ExecuteCommand(string.Format("LOGIN {0} {1}", Username, Password));
- if (ReadMultiline().EndsWith("(Success)"))
- {
- State = GmailState.Authorized;
- if (OnLogin != null)
- OnLogin.Invoke(this, null);
- }
- }
- }
- }
- public Mailbox List()
- {
- ExecuteCommand("LIST \"\" *");
- return Mailbox.Parse(ReadMultiline());
- }
- public bool Select(string Folder, out FolderData Data)
- {
- Data = new FolderData(Folder);
- Folder = Folder.Replace("Γ€", "&AOQ-");
- Folder = Folder.Replace("ΓΆ", "&APY-");
- ExecuteCommand("SELECT " + Folder);
- string Response = ReadMultiline();
- if (Response.EndsWith("(Success)"))
- {
- FolderData.Parse(Data, Response);
- State = GmailState.Selected;
- return true;
- }
- return false;
- }
- public enum FetchType
- {
- Text,
- Html
- }
- private void FetchBody(ref EmailMessage Message, FetchType Type)
- {
- string Command = "FETCH " + Message.ID + " BODY[{0}]";
- bool Continue = false;
- BodyPartEncoding ContentEncoding = BodyPartEncoding.UNKNOWN;
- Encoding BodyEncoding = Encoding.Default;
- switch (Type)
- {
- case FetchType.Text:
- if (Message.ContainsText())
- {
- BodyPart Part = Message.Parts[Message.TextIndex];
- ContentEncoding = Part.ContentEncoding;
- BodyEncoding = Part.BodyEncoding;
- Command = string.Format(Command, Part.Index);
- Continue = true;
- }
- break;
- case FetchType.Html:
- {
- if (Message.ContainsHtml())
- {
- BodyPart Part = Message.Parts[Message.HtmlIndex];
- ContentEncoding = Part.ContentEncoding;
- BodyEncoding = Part.BodyEncoding;
- Command = string.Format(Command, Part.Index);
- Continue = true;
- }
- }
- break;
- }
- if (Continue)
- {
- ExecuteCommand(Command);
- string Response = ReadLine();
- string ServerFinished = string.Format("TP{0} OK", CurrentCommand - 1);
- StringBuilder message = new StringBuilder();
- do
- {
- Response = ReadLine();
- if (Response.StartsWith(ServerFinished)) break;
- if (ContentEncoding == BodyPartEncoding.BASE64)
- {
- message.Append(Response);
- }
- else if (ContentEncoding == BodyPartEncoding.QUOTEDPRINTABLE)
- {
- if (Response.EndsWith("=") || Response.EndsWith(")"))
- {
- message.Append(Response.Substring(0, Response.Length - 1));
- }
- else
- {
- message.AppendLine(Response);
- }
- }
- else
- message.AppendLine(Response);
- } while (true);
- if (message.ToString().EndsWith(")"))
- message.Remove(message.Length - 1, 1);
- string MessageContents = message.ToString();
- if (ContentEncoding != BodyPartEncoding.BASE64)
- {
- MessageContents = Decoder.DecodeMessage(MessageContents, BodyEncoding);
- }
- if (Type == FetchType.Text)
- Message.Text = MessageContents;
- else
- Message.Html = MessageContents;
- }
- }
- public EmailMessage[] FetchLast(int Total, int Count)
- {
- List<EmailMessage> Emails = new List<EmailMessage>();
- for (int i = Total; i >= (Total - Count); i--)
- {
- Emails.Add(Fetch(i));
- }
- return Emails.ToArray();
- }
- public EmailMessage Fetch(int Number)
- {
- EmailMessage Message = new EmailMessage();
- Message.ID = (uint)Number;
- FetchBodystructure(ref Message);
- FetchHeaders(ref Message);
- FetchBody(ref Message, FetchType.Text);
- FetchBody(ref Message, FetchType.Html);
- return Message;
- }
- private void FetchHeaders(ref EmailMessage Message)
- {
- ExecuteCommand(string.Format("FETCH {0} (BODY[HEADER.FIELDS (FROM SUBJECT DATE)])", Message.ID));
- string Response = ReadMultiline();
- string[] Contents = Response.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
- for (int i = 0; i < Contents.Length; i++)
- {
- string Line = Contents[i];
- if (Line.StartsWith("Subject: "))
- {
- string Subject = Line.Substring(9);
- for (int Counter = i + 1; Counter < Contents.Length; Counter++)
- {
- string NextLine = Contents[Counter].TrimStart();
- if (NextLine.StartsWith(Subject.Substring(0, 2)))
- {
- Subject += NextLine;
- }
- else
- break;
- }
- Message.Subject = Decoder.DecodeMessage(Subject);
- }
- else if (Line.StartsWith("From: "))
- {
- Message.From = EmailAddress.Parse(Decoder.DecodeMessage(Line.Substring(6)));
- }
- else if (Line.StartsWith("Date: "))
- {
- int TimezoneIndex = Line.LastIndexOf(" ");
- string Date = Line.Substring(6, TimezoneIndex - 6);
- string Timezone = Line.Substring(TimezoneIndex + 1);
- Timezone = Timezone.Substring(0, 3);
- DateTime Time;
- if (DateTime.TryParse(Date, out Time))
- {
- int TimeDifference;
- if (int.TryParse(Timezone, out TimeDifference))
- {
- Message.Time = new DateTimeOffset(Time, new TimeSpan(TimeDifference, 0, 0));
- }
- }
- }
- }
- }
- private void FetchBodystructure(ref EmailMessage Message)
- {
- ExecuteCommand(string.Format("FETCH {0} BODYSTRUCTURE", Message.ID));
- string Response = ReadMultiline();
- // Email doesn't exists. Server sends only 'Finish'-Command
- if (ResponseEnd(Response)) return;
- #region Remove all unneccesary data from Response
- Response = Response.Replace("\r\n", "");
- Response = Response.Remove(0, Response.IndexOf(" (", Response.IndexOf("BODYSTRUCTURE")));
- Response = Response.Remove(Response.LastIndexOf("TP"));
- Response = Response.Trim();
- Response = Response.Remove(Response.Length - 1);
- #endregion
- Message.Parts = ParseBodystructure(Response);
- for (int i = 0; i < Message.Parts.Count; i++)
- {
- BodyPart Part = Message.Parts[i];
- if (Part.MediaType == "text/plain")
- {
- Message.TextIndex = i;
- }
- else if (Part.MediaType == "text/html")
- {
- Message.HtmlIndex = i;
- }
- }
- }
- private BodyPartList ParseBodystructure(string Data)
- {
- BodyPartList Parts = new BodyPartList();
- int counter = 0;
- int index = 1;
- int count = 0;
- do
- {
- int next = index;
- do
- {
- if (Data[next] == '(')
- counter++;
- else if (Data[next] == ')')
- counter--;
- next++;
- } while (counter > 0 || Data[next - 1] != ')');
- if (counter >= 0 && Data[index] == '(')
- {
- count++;
- if (Data.Substring(index, next - index).StartsWith("(("))
- {
- BodyPartList tmp = ParseBodystructure(Data.Substring(index, next));
- for (int j = 0; j < tmp.Count; j++)
- {
- tmp[j].Index = count.ToString() + "." + tmp[j].Index;
- Parts.Add(tmp[j]);
- }
- }
- else
- {
- BodyPart Part = new BodyPart(Data.Substring(index, next - index));
- Part.Index = count.ToString();
- Parts.Add(Part);
- }
- }
- else if (Parts.Count == 0)
- {
- BodyPart Part = new BodyPart(Data);
- Part.Index = "1";
- Parts.Add(Part);
- }
- index = next;
- } while (counter >= 0);
- return Parts;
- }
- private void ExecuteCommand(string Command)
- {
- Command = string.Format("TP{0} {1}\r\n", CurrentCommand++, Command);
- Stream.Write(Encoding.ASCII.GetBytes(Command));
- Stream.Flush();
- }
- private string ReadLine()
- {
- return Reader.ReadLine();
- }
- private bool ResponseEnd(string Response)
- {
- string End = string.Format("TP{0} OK", CurrentCommand - 1);
- return Response.StartsWith(End);
- }
- private string ReadMultiline()
- {
- string Response = Reader.ReadLine();
- string ServerOk = string.Format("TP{0} OK", CurrentCommand - 1);
- string ServerBad = string.Format("TP{0} BAD", CurrentCommand - 1);
- if (Response.StartsWith(ServerBad)) return "";
- while (!Response.StartsWith(ServerOk))
- {
- string CurrentLine = Reader.ReadLine();
- Response = Response + "\r\n" + CurrentLine;
- if (CurrentLine.StartsWith(ServerOk)) break;
- }
- return Response;
- }
- private bool ValidResponse(string Response)
- {
- return (Response.Length > 0 && Response[0] == '*');
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement