After creating a "reply to all" from an incoming email, I need to remove recipients that are not allowed to get this reply. But after creating the reply message, the recipients Lists (ToRecipients, CcRecipients, BccRecipients) of the reply message are empty.
ResponseMessage responseMessage = email.CreateReply(true);
foreach (EmailAddress toRecipient in responseMessage.ToRecipients)
{
if (! _outboundEmailAdresses.Contains(toRecipient.Address))
{
responseMessage.ToRecipients.Remove(toRecipient.Address);
}
}
`
If I iterate through email.ToRecipients, I see all the recipients. If I iterate through responseMessage.ToRecipients, I can't see any recipients. Shouldn't email.CreateReply(true) copy the email.from and email.ToRecipients addresses to the responseMessage?
This one's a bit confusing. Basically the ResponseMessage class implements EWS's CreateItem operation with the ReferenceItemId element, which allows you to send minimal information to the server. The idea is the server already has most of the info it needs to send a reply (like the original body, recipient list, etc), so you don't need to re-send that information. So the ResponseMessage doesn't get a copy of the recipients from the EmailMessage, because it doesn't need it.
You'll want to check the recipients of the original message, plus the sender. If they don't contain an unwanted address, then you don't need to do anything. If they do, then you'll want to set ResponseMessage.ToRecipients. If you do this, you need to add all of the desired addresses. Touching ResponseMessage.ToRecipients overrides the original recipient list.
Related
I need to send an emails (bulk sending), and I have two cases:
The same email sent into multiple recipients
Different emails sent into different recipients
How, in both cases, I can control statuses?
First case will return single x-message-id, but how it can be translated into separate status for each recipients? (delivered, opened and so on?)
Second case, I believe, need to be done by sending one-by one, is that correct? Or there is also method to send bulk emails in that case?
I'm using C# and official .NET library.
To send the same email sent to multiple recipients:
You can use the MailHelper.CreateSingleEmailToMultipleRecipients and you'll need to specify the text and HTML content in code. (Sample)
You can also use the MailHelper.CreateSingleTemplateEmailToMultipleRecipients method which will use a SendGrid Dynamic Email Template. In that case the email template is already stored in SendGrid and you simply provide the ID of the template.
There's a showAllRecipients named parameter which defaults to false. When false recipients cannot see other recipients, when true recipients can see other recipients.
I'll talk about retrieving the status's of the individual emails later.
To send different email to different people:
You can use MailHelper.CreateMultipleEmailsToMultipleRecipients which will use a single text and HTML body template, but you can add substitution tags and pass in substitution data so the email will be personalized for every recipient. (Sample)
You can construct a single MailMessage but use multiple Personalization objects to override any of the MailMessage properties for specific recipients. (Sample)
You can also construct multiple MailMessage objects and submit them individually to the API, although the above options are made for this scenario.
To send any of these emails, your API key must have the mail.send permission.
There are additional ways to send bulk email with SendGrid, which I documented here in much more detail.
As you noted, when you send email in bulk, only a single message ID is returned via the x-message-id header.
When you later try to retrieve the details using that message ID, you will not find any messages.
That is because the message ID in the x-message-id header is used as a base ID and the real message IDs will append another ID.
For example, x-message-id will return "W86EgYT6SQKk0lRflfLRsA", but when you retrieve one of the individual messages, it will looks something like this: "W86EgYT6SQKk0lRflfLRsA.filterdrecv-5645d9c87f-78xgx-1-62841247-82.1".
You can retrieve these messages via the E-Mail Activity API like this:
var queryParams = JsonSerializer.Serialize(new
{
query = $"msg_id LIKE '{messageId}%'",
limit = 10
});
var response = await client.RequestAsync(
method: SendGridClient.Method.GET,
urlPath: "messages",
queryParams: queryParams
);
Console.WriteLine(await response.Body.ReadAsStringAsync());
Take note of the query property which is has the $"msg_id LIKE '{messageId}%'" value.
This query will filter to messages that begin with the message ID returned from the bulk email (messageId), and as a result retrieve all the individual messages.
You cannot query these messages immediately after submitting the bulk email to SendGrid's queue as it takes some time for them to become available through the API.
In my code I queried these messages every 30 seconds until the count of the recipients in the bulk email matched the messages returned.
The resulting JSON data looks like this:
{
"messages": [
{
"from_email": "some#email.address",
"msg_id": "5QSczogTRHqFtiIkLxMtWA.filterdrecv-5645d9c87f-6r2ch-1-62847C63-2D.0",
"subject": "Sending with Twilio SendGrid is Fun",
"to_email": "some#email.address",
"status": "delivered",
"opens_count": 0,
"clicks_count": 0,
"last_event_time": "2022-05-18T05: 01: 05Z"
},
{
"from_email": "some#email.address",
"msg_id": "5QSczogTRHqFtiIkLxMtWA.filterdrecv-5645d9c87f-6r2ch-1-62847C63-2D.1",
"subject": "Sending with Twilio SendGrid is Fun",
"to_email": "some#email.address",
"status": "delivered",
"opens_count": 0,
"clicks_count": 0,
"last_event_time": "2022-05-18T05: 01: 05Z"
},
...
]
}
As you can see, this includes the status property.
Note: You must purchase additional email activity history to gain access to the Email Activity Feed API.
Note: To retrieve message via the Email Activity Feed API, your API key must have the email_activity.read permission.
This would be one way to retrieve the status of your email messages.
Another way to keep track of the status of email messages would be to create a public ASP.NET endpoint configure the URL as the SendGrid Event Webhook.
SendGrid will send an HTTP request to your ASP.NET endpoint for every event which you can use to update the status of email messages.
PS: You may already be doing this, but whether you're sending a single email to multiple recipients or multiple emails to multiple recipients, Twilio recommends setting the SendAt property on the SendGridMessage when sending bulk emails.
Quoting from the SendGrid docs:
This technique allows for a more efficient way to distribute large
email requests and can improve overall mail delivery time performance.
This functionality:
Improves efficiency of processing and distributing large volumes of email.
Reduces email pre-processing time.
Enables you to time email arrival to increase open rates.
Is available for free to all SendGrid customers.
I hope that answered all your questions, if not let me know. I can't wait to see what you build!
How to compare e-mail messages without using the body of the message?
For example:
John sent a message to Mary and "save" this message in my addin.
Both have the same addin.
When Mary receives the message, this message must be categorized because John already "save" the message.
How to identify that the message that Mary received is the same as the message that John sent("save") without using the body of the message?
Currently this is working as follows, a HASH is made with the following information:
Sender
Addressee
Subject
Message Body Text
This Hash is stored in the database, when Mary's Outlook triggers the event of the new message, a HASH with the same information is generated and compared in the database to see if it should be categorized or not.
The problem is that depending on the body size of the message, it is not performatic, it takes a long time to get the body of the message through the MailItem.Body property.
The purpose of not using the body of the message is solely to increase performance.
public string GetAssinatura(Outlook.MailItem email)
{
try
{
string corpoEmail = email.Body;//this is not performatic with big messages
var hash = GenerateHash(corpoEmail);
}
}
Conversation participants can reply or forward the message, so Outlook and most of the most frequently used e-mail clients change the subject to a default, Re: Subject for example.
Therefore, it is not possible to only have a hash of the participants and the subject.
Using the property:
MailItem.SentOn
It's possible generate that hash. The sender Outlook only will have that info after send the message. So the code must run when a new item is add in the Item_Send folder.
I am using mail kit to send receive mail, and manage all records in my database. I am storing all user action for particular mail and then execute it using my code.
I am storing message id in the table for the unique message, now I want to get the message using messageid. Is there any way to do it?
Firstly, don't expect the Message-Id header to be globally unique. Any hacker could easily create their own message and re-use a known Message-Id to try and confuse software that depends on Message-Ids being unique.
That said, you'll need to use the IMailFolder.Search() API combined with SearchQuery.HeaderContains() to search for messages with a particular Message-Id header.
var uids = folder.Search (SearchQuery.HeaderContains ("Message-Id", "blah#blah.com"));
I'm using MailChimp for .NET sending mails, but the wrapper for the recipient doesn't contain a type, which the is necessary for sending massmails.
MailChimp.Types.Mandrill.Messages.Recipient recipient = new MailChimp.Types.Mandrill.Messages.Recipient(member.EMail, member.Name);
Is it me who has missed something?
Quoted from MailChimp. Scroll down to "Tips for creating your HTML Campaign".
MailChimp does not use a BCC field as each recipient on your list is hidden from all other recipients on your list. We deliver a completely separate copy of your email to each recipient on your list, allowing you to personalize your content for each recipient, track clicks and opens, and address each email to the recipient's name.
I decided to use MCAPI.NET and changed the source adding a attribute to Recipient with name "to".
Setting this attribute to value "BCC" solved the problem.
Note : MailChimp is a Newsletter sending software where Mandrill is a transactional mail sending component.
I am writing a program that polls an incoming mailbox (to which anyone who knows about it can post), reformats the info, then forwards the mail on to the correct address according to a predefined convention. For example, the incoming mail has:
From = "anybody#somedomain.com"
To = "myincomingmailbox#mydomain.com"
Subject = "Subject"
Body = "recipient#anotherdomain.com+newline+Body"
Then I take that email, preserve the "From" and "Subject" fields, but I change the "To" address to recipient#anotherdomain.com, and format the rest of the body according to my template.
Thus far all OK - but I anticipate a problem with spam filters on the recipient domains, since they may react as if I'm spoofing the "From" address.
What is the correct way to preserve the headers from the original mail intact, such that all the SPF/DKIM headers remain on the outgoing email, and the recipient domains don't treat the incoming mail as possible spam/phishing mails?