Create mail in Exchange Online inbox programatically - exchange-server

Have been facing an issue since days about EWS. So my scenario is;
I was to programmatically sync GMAIL and EXCHANGE ONLINE. So here is what I have done;
Connect to Gmail using Gmail API
Fetch mail from gmail get the email body, to, from, attachment and
all other thing
connect to Exchange online using EWS 2.0
Now the problem is here, how can I create an email in Inbox which looks like incoming mail from the sender;
Here is the code I have done;
_service = new ExchangeService(ExchangeVersion.Exchange2013);
_service.TraceEnabled = true;
_service.Credentials = new WebCredentials("admin#xyz.onmicrosoft.com", "password");
_service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
_service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "xyz#xyz.onmicrosoft.com");
EmailMessage message = new EmailMessage(_service);
Random r = new Random();
message.Subject = "Email Message";
message.From = new EmailAddress("xyz#gmail.com");
message.Sender = new EmailAddress("xyz#gmail.com");
message.Body = new MessageBody(BodyType.HTML, "<HTML><body><h1>This is a voice mail.</h1></BODY></HTML>");
message.ToRecipients.Add(new EmailAddress(""));
message.Save(WellKnownFolderName.Inbox);
This way its creating an email in inbox but it shows as a draft mail. I dont want it, I want it to look as RECEIVED mail.
Am I doing anything wrong?

You need to set a couple of properties before saving the message.
// Set a delivery time
ExtendedPropertyDefinition PidTagMessageDeliveryTime =
new ExtendedPropertyDefinition(0x0E06, MapiPropertyType.SystemTime);
DateTime deliveryTime = DateTime.Now; // Or whatever deliver time you want
message.SetExtendedProperty(PidTagMessageDeliveryTime, deliveryTime);
// Indicate that this email is not a draft. Otherwise, the email will appear as a
// draft to clients.
ExtendedPropertyDefinition PR_MESSAGE_FLAGS_msgflag_read = new ExtendedPropertyDefinition(3591, MapiPropertyType.Integer);
message.SetExtendedProperty(PR_MESSAGE_FLAGS_msgflag_read, 1);
These properties aren't settable after the items is saved, so it's important to do it before the first Save call.

Related

Send Office365 e-mail using AzureAD authenticated user

I have a .Net Core MVC Web application that authenticates the user using AzureAD. At some stage I need to send an e-mail on behalf of that user.
I searched for some options and apparently I can do that using Microsoft Exchange Service or Office365 but for both options I need to get the user's credential.
An example using Office365 is below however I do not know how to user the signed in info to pass to the SMTP server.
My (partial) HomeController:
private readonly ClaimsPrincipal _principal;
public HomeController(IPrincipal principal){
_principal = principal as ClaimsPrincipal;
}
I can use _principal.FindFirst(ClaimTypes.Upn).Value to get the user's e-mail address but how do I get the password?
Am I in the right path or am I missing anything?
public static void SendEmail(string toAddress, string fromAddress, string subject, string content)
{
SmtpClient client = new SmtpClient();
client.Credentials = new NetworkCredential("", "");
client.Port = 587;
client.Host = "smtp.office365.com";
client.EnableSsl = true;
MailMessage newMail = new MailMessage();
newMail.To.Add(toAddress);
newMail.From = new MailAddress(fromAddress);
newMail.Subject = subject;
newMail.IsBodyHtml = true;
newMail.Body = "<html><body>" + content + "</body></html>";
client.Send(newMail);
}
I'm sorry if this is a broad question but I really need some light on how to achieve this. I'm happy to provide more details if necessary.
At some stage I need to send an e-mail on behalf of that user.
Per my understanding, you could use the cloud-based email service SendGrid to handle email delivery on behalf of your authenticated user's email address. The code for sending the email to test02#example.com for the user test01#example.com would look like this:
var client = new SendGridClient("<SendGrid-ApiKey>");
var msg = new SendGridMessage()
{
From = new EmailAddress("test01#example.com", "test01"),
Subject = "Hello World from the SendGrid CSharp SDK!",
PlainTextContent = "Hello, Email!",
HtmlContent = "<strong>Hello, Email!</strong>"
};
msg.AddTo(new EmailAddress("test02#example.com", "Test02"));
var response = await client.SendEmailAsync(msg);
Detailed tutorial, you could follow sendgrid-csharp.

How add attachment into embedded message using EWS

I have a message with ebbedded message, that has own attachment. I have to send this to server using EWS. I can send message with embedded message as attachment, but can't send its attachment, besause AttachmentType doesn't allow add attachment to attachment. Do you know any other ways to solve my problem?
One workaround in that situation that should work is to use the MIMEContent of the ItemAttachment eg
itemAttachment.Load(newPropertySet(ItemSchema.MimeContent));
and then either create a Message based on that or add that as an attachment on a new message eg
FolderId folderid= new FolderId(WellKnownFolderName.Inbox,"MailboxName");
Folder Inbox = Folder.Bind(service,folderid);
ItemView ivItemView = new ItemView(1) ;
FindItemsResults<Item> fiItems = service.FindItems(Inbox.Id,ivItemView);
if(fiItems.Items.Count == 1){
EmailMessage mail = new EmailMessage(service);
EmailMessage OriginalEmail = (EmailMessage)fiItems.Items[0];
PropertySet psPropset= new PropertySet(BasePropertySet.IdOnly);
psPropset.Add(ItemSchema.MimeContent);
psPropset.Add(ItemSchema.Subject);
OriginalEmail.Load(psPropset);
ItemAttachment Attachment = mail.Attachments.AddItemAttachment<EmailMessage>();
Attachment.Item.MimeContent = OriginalEmail.MimeContent;
ExtendedPropertyDefinition PR_Flags = new ExtendedPropertyDefinition(3591, MapiPropertyType.Integer);
Attachment.Item.SetExtendedProperty(PR_Flags,"1");
Attachment.Name = OriginalEmail.Subject;
mail.Subject = "See the Attached Email";
mail.ToRecipients.Add("glen.scales#domain.com");
mail.SendAndSaveCopy();
Cheers
Glen

How to get SMTPHost in custom workflow activity in MS Dynamics CRM?

I am trying to send email in custom workflow activity using SMTPClient instead of using Email entity and SendEmailRequest in MS Dynamics CRM custom workflow activity.
The reason I am doing this is because I want to send an calendar meeting invitation to the customer and not the email. For basics I got the code below:
MailMessage mail = new MailMessage("you#yourcompany.com", "user#hotmail.com");
SmtpClient client = new SmtpClient();
client.Port = 25;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Host = "smtp.google.com";
mail.Subject = "this is a test email.";
mail.Body = "this is my test email body";
client.Send(mail);
I intend to use DDay.iCal for the purpose.
Now this might seem to be a very basic question but I am stuck in how to get the Host name value in the custom workflow activity (instead of smtp.google.com).
Please advise.
Thanks,
I figured it out. It was in my email router configuration in "Email Server" column.

Forward email using EWS managed api keeping the headers

I am looking for a sample code on how to forward an existing email message (one that is already in my inbox) using the managed api.
When forwarded is there some way to keep a message original headers while forwarding it?
for example someone sent an email to me -i would like that ews will forward it to another recipient without changing the headers (original receive time from ,bcc etc...).
Given an EmailMessage object, you can just call the CreateForwareMessage() method:
var forwareMessage = item.CreateForward();
Regarding the other question: Get the MIME content of the mail and attach it to a new message:
item.Load(new PropertySet(BasePropertySet.IdOnly, ItemSchema.MimeContent));
var mail = new EmailMessage(service);
var attachment = mail.Attachments.AddFileAttachment("Original message.eml", item.MimeContent.Content);
attachment.ContentType = string.Format("message/rfc822; charset={0}", item.MimeContent.CharacterSet);
mail.ToRecipients.Add("hkrause#infinitec.de");
mail.Subject = "testmail";
mail.SendAndSaveCopy();
EDIT:
Create forward message and set reply to header:
var fw = item.CreateForward();
var fwMsg = fw.Save(WellKnownFolderName.Drafts);
fwMsg.ReplyTo.Add("personA#company.com");
fwMsg.SendAndSaveCopy();

Exchange Web Services (EWS) API "To" header for alias

I have an inbox set up in exchange, hello#mycompany.com
Additionally, there is an alias for this, news#mycompany.com, so all emails to the news address end up in the hello inbox.
Ideally, I want to be able to tell which alias an email has been sent to, using EWS.
When I send an email to news#mycompany.com, and examine the Internet headers of the message using Microsoft Outlook, the To: header reads To: Hello <news#mycompany.com> which is exactly what I want to see.
However, using EWS, when I look at the ToRecipients property of the message, the reported email address is always that of the primary SMTP address. Also the InternetMessageHeaders property of the Webservices.Data.Item does not contain the To: property. I also can't seem to see the correct address using EWSEditor to examine all the properties of the message.
The answer to this forum post seems to suggest that,
...The Information about the actual email address a message is sent to is stored in the recipients collection which you can't access (outside of exportmessage) in EWS...
How would I go about doing this programatically so I can find the correct To: address?
This works for me:
private static string GetToAddress()
{
ExchangeService exService = new ExchangeService();
exService.Credentials = new NetworkCredential("username", "password", "domain");
exService.Url = new Uri("https://youraddress/EWS/Exchange.asmx");
ExtendedPropertyDefinition PR_TRANSPORT_MESSAGE_HEADERS = new ExtendedPropertyDefinition(0x007D,MapiPropertyType.String);
PropertySet psPropSet = new PropertySet(BasePropertySet.FirstClassProperties)
{PR_TRANSPORT_MESSAGE_HEADERS, ItemSchema.MimeContent};
FindItemsResults<Item> fiResults = exService.FindItems(WellKnownFolderName.Inbox, new ItemView(1));
foreach (Item itItem in fiResults.Items)
{
itItem.Load(psPropSet);
Object valHeaders;
if (itItem.TryGetProperty(PR_TRANSPORT_MESSAGE_HEADERS, out valHeaders))
{
Regex regex = new Regex(#"To:.*<(.+)>");
Match match = regex.Match(valHeaders.ToString());
if (match.Groups.Count == 2)
return match.Groups[1].Value;
}
return ToAddress;
}
return "Cannot find ToAddress";
}
The code is from:
http://social.technet.microsoft.com/Forums/en-au/exchangesvrdevelopment/thread/1e5bbde0-218e-466e-afcc-cb60bc2ba692

Resources