Reading emails from Gmail in C#
Using the library from: https://github.com/pmengal/MailSystem.NET
Here is my complete code sample:
Email Repository
using System.Collections.Generic;
using System.Linq;
using ActiveUp.Net.Mail;
namespace GmailReadImapEmail
{
public class MailRepository
{
private Imap4Client client;
public MailRepository(string mailServer, int port, bool ssl, string login, string password)
{
if (ssl)
Client.ConnectSsl(mailServer, port);
else
Client.Connect(mailServer, port);
Client.Login(login, password);
}
public IEnumerable<Message> GetAllMails(string mailBox)
{
return GetMails(mailBox, "ALL").Cast<Message>();
}
public IEnumerable<Message> GetUnreadMails(string mailBox)
{
return GetMails(mailBox, "UNSEEN").Cast<Message>();
}
protected Imap4Client Client
{
get { return client ?? (client = new Imap4Client()); }
}
private MessageCollection GetMails(string mailBox, string searchPhrase)
{
Mailbox mails = Client.SelectMailbox(mailBox);
MessageCollection messages = mails.SearchParse(searchPhrase);
return messages;
}
}
}
Usage
[TestMethod]
public void ReadImap()
{
var mailRepository = new MailRepository(
"imap.gmail.com",
993,
true,
"yourEmailAddress@gmail.com",
"yourPassword"
);
var emailList = mailRepository.GetAllMails("inbox");
foreach (Message email in emailList)
{
Console.WriteLine("<p>{0}: {1}</p><p>{2}</p>", email.From, email.Subject, email.BodyHtml.Text);
if (email.Attachments.Count > 0)
{
foreach (MimePart attachment in email.Attachments)
{
Console.WriteLine("<p>Attachment: {0} {1}</p>", attachment.ContentName, attachment.ContentType.MimeType);
}
}
}
}
Another example, this time using MailKit
public class MailRepository : IMailRepository
{
private readonly string mailServer, login, password;
private readonly int port;
private readonly bool ssl;
public MailRepository(string mailServer, int port, bool ssl, string login, string password)
{
this.mailServer = mailServer;
this.port = port;
this.ssl = ssl;
this.login = login;
this.password = password;
}
public IEnumerable<string> GetUnreadMails()
{
var messages = new List<string>();
using (var client = new ImapClient())
{
client.Connect(mailServer, port, ssl);
// Note: since we don't have an OAuth2 token, disable
// the XOAUTH2 authentication mechanism.
client.AuthenticationMechanisms.Remove("XOAUTH2");
client.Authenticate(login, password);
// The Inbox folder is always available on all IMAP servers...
var inbox = client.Inbox;
inbox.Open(FolderAccess.ReadOnly);
var results = inbox.Search(SearchOptions.All, SearchQuery.Not(SearchQuery.Seen));
foreach (var uniqueId in results.UniqueIds)
{
var message = inbox.GetMessage(uniqueId);
messages.Add(message.HtmlBody);
//Mark message as read
//inbox.AddFlags(uniqueId, MessageFlags.Seen, true);
}
client.Disconnect(true);
}
return messages;
}
public IEnumerable<string> GetAllMails()
{
var messages = new List<string>();
using (var client = new ImapClient())
{
client.Connect(mailServer, port, ssl);
// Note: since we don't have an OAuth2 token, disable
// the XOAUTH2 authentication mechanism.
client.AuthenticationMechanisms.Remove("XOAUTH2");
client.Authenticate(login, password);
// The Inbox folder is always available on all IMAP servers...
var inbox = client.Inbox;
inbox.Open(FolderAccess.ReadOnly);
var results = inbox.Search(SearchOptions.All, SearchQuery.NotSeen);
foreach (var uniqueId in results.UniqueIds)
{
var message = inbox.GetMessage(uniqueId);
messages.Add(message.HtmlBody);
//Mark message as read
//inbox.AddFlags(uniqueId, MessageFlags.Seen, true);
}
client.Disconnect(true);
}
return messages;
}
}
Usage
[Test]
public void GetAllEmails()
{
var mailRepository = new MailRepository("imap.gmail.com", 993, true, "YOUREMAILHERE@gmail.com", "YOURPASSWORDHERE");
var allEmails = mailRepository.GetAllMails();
foreach(var email in allEmails)
{
Console.WriteLine(email);
}
Assert.IsTrue(allEmails.ToList().Any());
}
Reading Emails from Gmail C# - IMAP
You should use the solution of the second post of the topic were you have found something, S22.Imap.
(Here you can find a compiled version).
After download, you can read the documentation. It is simple and readable.
Actually, I use this library and that works well !
How can I download emails from Gmail using C#/WinForms?
No you dont require to have Google API for getting(downloading) emails from Gmail account. You can read more about Reading Gmail Inbox Message
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;
using System.Net.NetworkInformation;
using System.Net.Security;
using System.Net.Sockets;
namespace mail
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
Imap client = new Imap();
// connect to server
client.Connect("imap.gmail.com", 993, SslMode.Implicit);
// authenticate
client.Login("username", "password");
// select folder
client.SelectFolder("Inbox");
int NoOfEmailsPerPage = 10;
int totalEmails = client.CurrentFolder.TotalMessageCount;
// get message list - envelope headers
ImapMessageCollection messages = client.GetMessageList(ImapListFields.Envelope);
// display info about each message
foreach (ImapMessageInfo message in messages)
{
TableCell noCell = new TableCell();
noCell.CssClass = "emails-table-cell";
noCell.Text = Convert.ToString(message.To);
TableCell fromCell = new TableCell();
fromCell.CssClass = "emails-table-cell";
fromCell.Text = Convert.ToString(message.From);
TableCell subjectCell = new TableCell();
subjectCell.CssClass = "emails-table-cell";
subjectCell.Style["width"] = "300px";
subjectCell.Text = Convert.ToString(message.Subject);
TableCell dateCell = new TableCell();
dateCell.CssClass = "emails-table-cell";
if (message.Date.OriginalTime != DateTime.MinValue)
dateCell.Text = message.Date.OriginalTime.ToString();
TableRow emailRow = new TableRow();
emailRow.Cells.Add(noCell);
emailRow.Cells.Add(fromCell);
emailRow.Cells.Add(subjectCell);
emailRow.Cells.Add(dateCell);
EmailsTable.Rows.AddAt(2 + 0, emailRow);
}
int totalPages;
int mod = totalEmails % NoOfEmailsPerPage;
if (mod == 0)
totalPages = totalEmails / NoOfEmailsPerPage;
else
totalPages = ((totalEmails - mod) / NoOfEmailsPerPage) + 1;
}
}
}
How to retrieve my Gmail messages using Gmail API?
Currently for some reason or another many of the properties are coming back null
from any of the requests. We can still get around that if we have a list of the email ids. We then can use these email ids to send out another request to retrieve further details: from
, date
, subject
, and body
. @DalmTo was on the right track as well, but not close enough about the headers as it has changed recently which will require a few more requests.
private async Task getEmails()
{
try
{
UserCredential credential;
using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
// This OAuth 2.0 access scope allows for read-only access to the authenticated
// user's account, but not other types of account access.
new[] { GmailService.Scope.GmailReadonly, GmailService.Scope.MailGoogleCom, GmailService.Scope.GmailModify },
"NAME OF ACCOUNT NOT EMAIL ADDRESS",
CancellationToken.None,
new FileDataStore(this.GetType().ToString())
);
}
var gmailService = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = this.GetType().ToString()
});
var emailListRequest = gmailService.Users.Messages.List("EMAILADDRESSHERE");
emailListRequest.LabelIds = "INBOX";
emailListRequest.IncludeSpamTrash = false;
//emailListRequest.Q = "is:unread"; // This was added because I only wanted unread emails...
// Get our emails
var emailListResponse = await emailListRequest.ExecuteAsync();
if (emailListResponse != null && emailListResponse.Messages != null)
{
// Loop through each email and get what fields you want...
foreach (var email in emailListResponse.Messages)
{
var emailInfoRequest = gmailService.Users.Messages.Get("EMAIL ADDRESS HERE", email.Id);
// Make another request for that email id...
var emailInfoResponse = await emailInfoRequest.ExecuteAsync();
if (emailInfoResponse != null)
{
String from = "";
String date = "";
String subject = "";
String body = "";
// Loop through the headers and get the fields we need...
foreach (var mParts in emailInfoResponse.Payload.Headers)
{
if (mParts.Name == "Date")
{
date = mParts.Value;
}
else if(mParts.Name == "From" )
{
from = mParts.Value;
}
else if (mParts.Name == "Subject")
{
subject = mParts.Value;
}
if (date != "" && from != "")
{
if (emailInfoResponse.Payload.Parts == null && emailInfoResponse.Payload.Body != null)
{
body = emailInfoResponse.Payload.Body.Data;
}
else
{
body = getNestedParts(emailInfoResponse.Payload.Parts, "");
}
// Need to replace some characters as the data for the email's body is base64
String codedBody = body.Replace("-", "+");
codedBody = codedBody.Replace("_", "/");
byte[] data = Convert.FromBase64String(codedBody);
body = Encoding.UTF8.GetString(data);
// Now you have the data you want...
}
}
}
}
}
}
catch (Exception)
{
MessageBox.Show("Failed to get messages!", "Failed Messages!", MessageBoxButtons.OK);
}
}
static String getNestedParts(IList<MessagePart> part, string curr)
{
string str = curr;
if (part == null)
{
return str;
}
else
{
foreach (var parts in part)
{
if (parts.Parts == null)
{
if (parts.Body != null && parts.Body.Data != null)
{
str += parts.Body.Data;
}
}
else
{
return getNestedParts(parts.Parts, str);
}
}
return str;
}
}
Currently, this method will retrieve all email ids and for each email id get the subject
,from
, date
and body
of each email. There are comments throughout the method. If there is something you do not understand, please let me know. On another note: this was tested again before posting this as an answer.
Related Topics
Sending Windows Key Using Sendkeys
How to Force My C# Winforms Program Run as Administrator on Any Computer
C# Wait for User to Finish Typing in a Text Box
How to Optionally Turn Off the JSONignore Attribute at Runtime
Right Way to Dispose Image/Bitmap and Picturebox
Get the Default Timezone for a Country (Via Cultureinfo)
Hangfire - Multi Tenant, ASP.NET Core - Resolving the Correct Tenant
How to Include Other Files to the Output Directory in C# Upon Build
How to Retrieve Disk Information in C#
What Does "Yield Break;" Do in C#
.Net Core Identity Server 4 Authentication VS Identity Authentication
When Would You Use Delegates in C#
Wpf Openfiledialog with the Mvvm Pattern
Auto Versioning in Visual Studio 2017 (.Net Core)
Bring Another Processes Window to Foreground When It Has Showintaskbar = False