I want to fetch the details from my outlook mailbox but don't have the Microsoft exchange server. I only have cloud-based services.
I tried to use the below-given code but that is an exchange server API solution. The second method is to open the outlook app and then accessing the mailbox but doesn't want this solution.
try
{
'Mailbox credentials'
string emailAddress = AppSettings.Office365EmailAddress;
string password = AppSettings.Office365Password;
ServicePointManager.ServerCertificateValidationCallback =
CertificateValidationCallBack;
ExchangeService service = new
ExchangeService(ExchangeVersion.Exchange2013_SP1);
service.Credentials = new WebCredentials(emailAddress, password);
service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
service.PreAuthenticate = true;
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress,
emailAddress);
ItemView view = new ItemView(int.MaxValue);
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Inbox,
SetFilter(), view);
DataTable dtEmails = GenerateEmailDataTable();
DataRow dr = dtEmails.NewRow();
foreach (Item item in findResults.Items)
{
if (item.Subject != null)
{
Match match = Regex.Match(item.Subject.ToString(), regJMSNumber);
if (match != null)
{
dr["EmailTo"] = item.DisplayTo.ToString();
dr["EmailFrom"] = item.DisplayTo.ToString();
dr["EmailCC"] = item.DisplayCc.ToString();
dr["EmailBCC"] = item.DisplayTo.ToString();
dr["EmailSubject"] = item.Subject.ToString();
dr["EmailBody"] = item.Body.ToString();
dr["CreatedOn"] = item.Subject.ToString();
dr["IsActive"] = true;
}
else
{
Console.WriteLine("Subject Not Match");
}
}
}
}
'Error handler.'
catch (System.Exception e)
{
Console.WriteLine("{0} Exception caught: ", e);
}
finally
{
}
Another approach is the Power Automate option but I want to do it programmatically.
Used https://outlook.office365.com/EWS/Exchange.asmx API.
When I am using EWS (exchange API), the application throwing a 401 Unauthorised requests failed exception.
Please tell me any other way to track the outlook emails with all details like EmailTo, EmailSent, EmailSubject, EmailBody, EmailCC, EmailBCC, and all the trailing messages.
Related
I've written a mail method and I'm setting the from email address but when the customer receives it, it's the same as the username that is used to authenticate the email.
I've tried to set the email right before the send and it still comes out wrong:
When I check the message, as shown above, the from is correct but the customer receives it from the username field instead.
public static EmailResults SendEmail(EmailSettings emailSettings)
{
var emailResults = new EmailResults();
try
{
// using mimekit that the msdn smtpclient webpage suggested using
// http://www.mimekit.net/docs/html/Introduction.htm
if (emailSettings.TestModeEnabled)
{
emailResults.IsSuccessful = true;
emailResults.Message = "SendEmail disabled due to TestModeEnabled being set to true.";
return emailResults;
}
// use the mimemessage to create the message to send
var message = new MimeMessage();
message.From.Add(emailSettings.FromEmail);
message.Subject = emailSettings.EmailSubject;
// to email has the option for multiple emails to be sent to
// loop through them and add them all to the message
foreach (var mailboxAddress in emailSettings.ToEmail)
{
message.To.Add(mailboxAddress);
}
// attach file if present
var builder = new BodyBuilder();
if (emailSettings.FileAttachments != null)
{
foreach (var file in emailSettings.FileAttachments)
{
if (File.Exists(file))
{
builder.Attachments.Add(file);
}
}
}
builder.HtmlBody = emailSettings.EmailBody;
message.Body = builder.ToMessageBody();
//// http://www.mimekit.net/docs/html/Creating-Messages.htm
//// A TextPart is a leaf-node MIME part with a text media-type. The first argument to the
//// TextPart constructor specifies the media-subtype, in this case, plain. Another media
//// subtype you are probably familiar with is the html subtype. Some other examples
//// include enriched, rtf, and xml.
//message.Body = new TextPart("html")
//{
// Text = emailSettings.EmailBody
//};
// bcc has the option for multiple emails to be sent to
// loop through them and add them all to the message
if (emailSettings.BccEmail != null)
{
foreach (var mailboxAddress in emailSettings.BccEmail)
{
message.Bcc.Add(mailboxAddress);
}
}
// *************** SEND EMAIL *******************
var client = emailSettings.EnableSmtpLog ? new MailKit.Net.Smtp.SmtpClient(new ProtocolLogger(GlobalVariables.SmptpLogFile)) : new MailKit.Net.Smtp.SmtpClient();
using (client)
{
if (emailSettings.SmtpServer.Contains("gmail.com"))
{
// Note: since we don't have an OAuth2 token, disable
// the XOAUTH2 authentication mechanism.
client.AuthenticationMechanisms.Remove("XOAUTH2");
}
client.SslProtocols = System.Security.Authentication.SslProtocols.Tls12;
//accept all SSL certificates
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
// client.Connect(emailSettings.SmtpServer, emailSettings.SmtpPort, emailSettings.IsSslEnabled);
client.Connect(emailSettings.SmtpServer, emailSettings.SmtpPort, emailSettings.AuthType);
if (emailSettings.IsAuthenticationRequired)
{
// Note: only needed if the SMTP server requires authentication
client.Authenticate(emailSettings.SmtpUsername, emailSettings.SmtpPassword);
}
if (emailSettings.TimeOut == 0) emailSettings.TimeOut = 10;
client.Timeout = emailSettings.TimeOut * 1000;
//message.From.Add(new MailboxAddress("someone#somewhere.net"));
client.Send(message);
client.Disconnect(true);
}
// if we reached this far, then the email was sent successfully
emailResults.Message = "Successfully sent.";
emailResults.IsSuccessful = true;
return emailResults;
}
catch (AuthenticationException e)
{
Logging.LogException("SmtpClient.SendEmail", "Error attempting to send email.", e);
emailResults.IsSuccessful = false;
emailResults.Message = "Invalid username or password.";
return emailResults;
}
catch (Exception e)
{
Logging.LogException("SmtpClient.SendEmail", "Error attempting to send email.", e);
emailResults.IsSuccessful = false;
if (e.Message.Contains("error occurred while attempting to establish an SSL or TLS connection"))
{
emailResults.Message = "An error occurred while attempting to establish a secure connection.\r\n\r\nPlease check your email settings.";
}
else
{
emailResults.Message = e.Message;
}
return emailResults;
}
}
Anyone have any suggestions on what I'm doing wrong?
For anyone who runs in to this again...
This particular issue is specific to Gmail. I'm not sure if other email hosts do the same.
If you are setting the from email address to "person1#email.com" but authenticating with "person2#gmail.com", Gmail will override the from email address with the authentication email address. You have no control over this.
Go to the Gmail account, into settings, and add the alias address in the "Send Mail As" section. The outgoing email should now display with the alias address rather than the authenticating address.
I am trying to fetch email body from exchange server for an appointment for a particular room but did not get a success. Verified all the blogs over internet but nothing was of any help. Here is the code where i am trying to contact exchange server to get the details:
Approach A
service.GetUserAvailability
(
attendees,
new TimeWindow(twStart, twEnd),
AvailabilityData.FreeBusy
).AttendeesAvailability[0].CalendarEvents;
Approach B
public class MailItem
{
public string From;
public string[] Recipients;
public string Subject;
public string Body;
}
public static MailItem[] GetUnreadMailFromInbox(ExchangeService service, string address)
{
// Address is the email address for an meeting room
try
{
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, address);
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Inbox, new ItemView(128));
ServiceResponseCollection<GetItemResponse> items =
service.BindToItems(findResults.Select(item => item.Id), new PropertySet(BasePropertySet.FirstClassProperties, EmailMessageSchema.From, EmailMessageSchema.ToRecipients));
FindItemsResults<Item> findResults2 = service.FindItems(WellKnownFolderName.Calendar, new ItemView(128));
ServiceResponseCollection<GetItemResponse> items2 =
service.BindToItems(findResults2.Select(item2 => item2.Id), new PropertySet(BasePropertySet.FirstClassProperties, EmailMessageSchema.From, EmailMessageSchema.ToRecipients));
return items.Select(item =>
{
return new MailItem()
{
From = address,
Recipients = ((Microsoft.Exchange.WebServices.Data.EmailAddressCollection)item.Item[EmailMessageSchema.ToRecipients]).Select(recipient => recipient.Address).ToArray(),
Subject = item.Item.Subject,
Body = item.Item.Body.ToString(),
};
}).ToArray();
}
catch (Exception ex)
{
throw ex;
}
}
I need a solution for fetching the body content for appointments from exchange server.
Assuming you are already connecting to the Exchange service successfully and only trying to retrieve appointments body part please try this.
Try Adding EmailMessageSchema.Body to your property set.
service.BindToItems(findResults2.Select(item2 => item2.Id), new PropertySet(BasePropertySet.FirstClassProperties, EmailMessageSchema.From, EmailMessageSchema.Body, EmailMessageSchema.ToRecipients));
We have an email coming at regular intervals (the request will be user driven), containing an Excel attachment. The goal is to extract the attachment from the email automatically, and pass it on to the method that will deal with the data in the file.
I'd like to stay away from 3rd party tools or libraries, and I'd like to keep this as simple as possible, minimal checks and features, literally just download the mail, save the attachment, if the email address matches the known source (to block spam).
From researching, there are 3 possible solutions. Which would be the most sensible route? And are there other options? Can anybody point me to relevant (and recent) tutorials?
Download using a 3rd party POP client
Write my own functionality, possibly using Exchange EWS (Preferred option) (using C#, VS2010)
Rather have Outlook download it, and then extract the attachment from Outlook
Here is an example of how I do it with our system. Let me know if you want me to explain anything as I did have to post this pretty quick.
namespace Namespace.Email
{
public class EmailLinker
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
public EmailLinker()
{
service.Credentials = new NetworkCredential("username", "password", "domain");
service.AutodiscoverUrl("email#email.com");
}
public void linkEmails()
{
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Inbox, new ItemView(128));
if (findResults.TotalCount > 0)
{
ServiceResponseCollection<GetItemResponse> items = service.BindToItems(findResults.Select(item => item.Id), new PropertySet(BasePropertySet.FirstClassProperties, EmailMessageSchema.From, EmailMessageSchema.ToRecipients));
foreach (GetItemResponse i in items)
{
MailItem m = new MailItem();
Item it = i.Item;
m.From = ((Microsoft.Exchange.WebServices.Data.EmailAddress)it[EmailMessageSchema.From]).Address;
m.Recipients = ((Microsoft.Exchange.WebServices.Data.EmailAddressCollection)it[EmailMessageSchema.ToRecipients]).Select(r => r.Address).ToArray();
m.Subject = it.Subject;
m.Body = it.Body.Text;
m.Recieved = it.DateTimeReceived;
m.attachments = it.Attachments;
foreach (Attachment a in m.attachments)
this.uploadAttachments(a);
i.Item.Delete(DeleteMode.HardDelete);
}
}
}
private void uploadAttachments(Attachment a)
{
ContentFile cf = new ContentFile();
cf.Name = a.Name;
cf.Size = a.Size;
cf.ContentType = MimeTypeMap.GetMimeType(Path.GetExtension(a.Name).Replace(".",""));
FileAttachment fa = (FileAttachment)a;
fa.Load();
cf.Data = fa.Content;
cf.DateAdded = DateTime.Now;
cf.save();
}
public class MailItem
{
public int id;
public string From;
public string[] Recipients;
public string Subject;
public string Body;
public DateTime Recieved;
public string RecievedString
{
get
{
return Recieved.ToShortDateString() + " " + Recieved.ToShortTimeString();
}
}
public AttachmentCollection attachments;
}
}
}
public class KCSExchangeLink : IKCSExchangeLink
{
private bool CertificateValidationCallBack(
object sender,
System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
// If the certificate is a valid, signed certificate, return true.
if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
{
return true;
}
// If there are errors in the certificate chain, look at each error to determine the cause.
if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) != 0)
{
if (chain != null && chain.ChainStatus != null)
{
foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus status in chain.ChainStatus)
{
if ((certificate.Subject == certificate.Issuer) &&
(status.Status == System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.UntrustedRoot))
{
// Self-signed certificates with an untrusted root are valid.
continue;
}
else
{
if (status.Status != System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.NoError)
{
// If there are any other errors in the certificate chain, the certificate is invalid,
// so the method returns false.
return false;
}
}
}
}
// When processing reaches this line, the only errors in the certificate chain are
// untrusted root errors for self-signed certificates. These certificates are valid
// for default Exchange server installations, so return true.
return true;
}
else
{
// In all other cases, return false.
return false;
}
}
private bool RedirectionUrlValidationCallback(string redirectionUrl)
{
// The default for the validation callback is to reject the URL.
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
// Validate the contents of the redirection URL. In this simple validation
// callback, the redirection URL is considered valid if it is using HTTPS
// to encrypt the authentication credentials.
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
public void SaveAttachment(string email, string password, string downloadfolder, string fromaddress)
{
ServicePointManager.ServerCertificateValidationCallback = CertificateValidationCallBack;
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Credentials = new WebCredentials(email, password);
service.TraceEnabled = true;
service.TraceFlags = TraceFlags.All;
service.AutodiscoverUrl(email, RedirectionUrlValidationCallback);
// Bind the Inbox folder to the service object.
Folder inbox = Folder.Bind(service, WellKnownFolderName.Inbox);
// The search filter to get unread email.
SearchFilter sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
ItemView view = new ItemView(1);
// Fire the query for the unread items.
// This method call results in a FindItem call to EWS.
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Inbox, sf, view);
foreach (EmailMessage item in findResults)
{
item.Load();
/* download attachment if any */
if (item.HasAttachments && item.Attachments[0] is FileAttachment && item.From.Address == fromaddress)
{
FileAttachment fileAttachment = item.Attachments[0] as FileAttachment;
/* download attachment to folder */
fileAttachment.Load(downloadfolder + fileAttachment.Name);
}
/* mark email as read */
item.IsRead = true;
item.Update(ConflictResolutionMode.AlwaysOverwrite);
}
}
}
Im trying to find a method in mailkit that executes the command "Execute append" in IMAP, in C# i would do it like:
MailMessage mg = null;
using (ImapClient cl = new ImapClient("imap.gmail.com"))
{
cl.Port = 993;
cl.Ssl = true;
cl.UserName = "xxxxx";
cl.Password = "yyyyy";
var bl = cl.Authenticate();
if (bl == true)
{
//Add Draft
var smg = new SmtpMessage("xxx#gmail.com", "yyy#hotmail.com","yyy#hotmail.com", "This is a test mail.", "Hi.Is it correct??");
cl.ExecuteAppend("GMail/Drafts", smg.GetDataText(), "\\Draft",DateTimeOffset.Now);
}
}
However observing MailKit ImapClient, i dont have this option..
How can i execute append in MailKit IMAP?
After some hours searching....
using (var client = new ImapClient())
{
try
{
client.Connect(ConfigurationManager.AppSettings["ImapServer"], int.Parse(ConfigurationManager.AppSettings["ImapPort"]), SecureSocketOptions.Auto);
// Note: since we don't have an OAuth2 token, disable
// the XOAUTH2 authentication mechanism.
client.AuthenticationMechanisms.Remove("XOAUTH2");
// MailKit uses by default ntlm authentication
client.Authenticate("username", "password");
var draftFolder = client.GetFolder(SpecialFolder.Drafts);
if (draftFolder != null)
{
draftFolder.Open(FolderAccess.ReadWrite);
draftFolder.Append(message, MessageFlags.Draft);
draftFolder.Expunge();
}
else
{
var toplevel = client.GetFolder(client.PersonalNamespaces[0]);
var DraftFolder = toplevel.Create(SpecialFolder.Drafts.ToString(), true);
DraftFolder.Open(FolderAccess.ReadWrite);
DraftFolder.Append(message, MessageFlags.Draft);
DraftFolder.Expunge();
}
}
catch (Exception ex)
{
throw new ApplicationException("IMAPException has occured: " + ex.Message);
}
client.Disconnect(true);
}
With reference to my previous question, I already wrote my program and it is working awesome when I am using VS2008 for run it.
I have two more questions:
1. I want to check with you guys when I run my program all the mail are appearing in VS output as xml file, but I never used to print them in output. is it usual for all or I need to add something to remove it. I feel it takes long time from my PC to show mails in output.
2. my second question is that when I want to use only exe file stand alone(run program via exe file not with VS ) I am receiving below error and program is hanging & close.
"MailReader has encountered a problem and needs to close. We are
sorry for the inconvenience."
As I mentioned above this program is working fine in VS.
I copy part of my code that read mails and split them for your reference.
public void ReadMail()
{
ServicePointManager.ServerCertificateValidationCallback += delegate(object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors) { return true; };
try
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.TraceEnabled = true;
service.Credentials = new WebCredentials(_username, _password); //Modify this
service.Url = new Uri(_exchange); //Modify this
service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Url = new Uri(_exchange);
service.TraceEnabled = true;
service.Credentials = new WebCredentials(_username, _password); //Modify this
service.Url = new Uri(_exchange);
//SearchFilter to get unreaded messages only.
SearchFilter sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
ItemView itemview = new ItemView(Int16.MaxValue);
//DateTime searchdate = new DateTime(2012, 7, 6); //Year, month, day
SearchFilter greaterthanfilter = new SearchFilter.IsGreaterThan(ItemSchema.DateTimeSent, Convert.ToDateTime(startDate));
SearchFilter lessthanfilter = new SearchFilter.IsLessThan(ItemSchema.DateTimeSent,Convert.ToDateTime(finishDate));
SearchFilter[] f = { greaterthanfilter, lessthanfilter };
SearchFilter filter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, f);
//Folder folder = Folder.Bind(this.m_Service, WellKnownFolderName.MsgFolderRoot); //Or the folder you want to search in
//FindItemsResults<Item> results = folder.FindItems(filter, new ItemView(1000));
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.SentItems,filter, itemview);
Action action = () => fr.setText(findResults.Items.Count + "mails need to analysis from "+startDate +" to "+ finishDate);
fr.Invoke(action, null);
action = () => fr.setMaximumProgressBar(findResults.Items.Count);
fr.Invoke(action, null);
dmd = new List<DailyMailDetails>();
foreach (Item item in findResults.Items)
{
string messageDate = "Error in Date";
string messageSubj = "Error in Subject";
int index = 0;
try
{
PropertySet propertySet = new PropertySet(BasePropertySet.FirstClassProperties, ItemSchema.DateTimeSent, ItemSchema.Body, ItemSchema.Subject);
propertySet.RequestedBodyType = BodyType.Text;
EmailMessage message = EmailMessage.Bind(service, item.Id, propertySet);
string temp = startSign.ToUpper();
int start = message.Body.Text.ToUpper().IndexOf(temp) + temp.Length;
int end = message.Body.Text.ToUpper().IndexOf(finishSign.ToUpper());
int len = end - start;
string text = message.Body.Text.Substring(start, len);
index = findDmdIndex(message.DateTimeSent.ToShortDateString().ToString());
if (index == -1)
{
dmd.Add(new DailyMailDetails(message.DateTimeSent.ToShortDateString().ToString(), (List<PeopleSigniture>)Extensions.Clone<PeopleSigniture>(OrginallistPeopleSign)));
index = dmd.Count - 1;
}
bool signExist = false;
for (int i = 0; i < listPeopleSign.Count; i++)
if (text.ToUpper().Contains(dmd[index].peopleSign[i].Signiture.ToUpper()))
{
dmd[index].peopleSign[i].addResponse(message.DateTimeSent.ToString(), message.Subject.ToString());
signExist = true;
break;
}
messageDate = message.DateTimeSent.ToString();
messageSubj = message.Subject.ToString();
if (!signExist)
dmd[index].peopleSign[dmd[index].peopleSign.Count - 2].addResponse(message.DateTimeSent.ToString(), message.Subject.ToString());
}
catch (Exception ex)
{
dmd[index].peopleSign[dmd[index].peopleSign.Count - 1].addResponse(messageDate, messageSubj);
}
action = () => fr.increasePrograss();
fr.Invoke(action, null);
}
}
catch (Exception ex)
{
MessageBox.Show("Class: Mail Function:ReadMail" + ex.Message);
}
Action action2 = () => fr.setText(ToString(true),dmd);
fr.Invoke(action2, null);
}
For issue #1 - you are viewing the XML output likely because you have EWS tracing enabled. You need to set ExchangeService.TraceEnabled to false or comment it out entirely. (You also have many duplicate lines of code you need to cleanup.)
service.TraceEnabled = false;
For issue #2 - you need to determine the actual .NET exception. Without this - we cannot help you further. It could be crashing for countless reasons. Please provide a stack trace.