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"));
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 trying to discover if there is a way to determine the internet message ID after sending an email using the EWS Managed API. I understand you can go in there and get the results from the sent box, but the server that is sending these emails is sending multiple emails at a time from different services.
No you can't, basically because EWS sends message Asynchronously the Id isn't available see https://social.msdn.microsoft.com/Forums/azure/en-US/dd034b8c-ffa1-4ae0-9025-45fcf520c9e5/updateitem-does-not-return-itemid?forum=exchangesvrdevelopment
As a work around you might want to consider setting the Internet messageId on the Message before you send it. As long as it valid and unique it should work okay eg
ExtendedPropertyDefinition PidTagInternetMessageId = new ExtendedPropertyDefinition(4149, MapiPropertyType.String);
EmailMessage ema = new EmailMessage(service);
ema.Subject ="test from ews";
ema.Body = new MessageBody("test<br>Rgds<>");
ema.ToRecipients.Add("gscales#domain.com");
ema.SetExtendedProperty(PidTagInternetMessageId,("<" +Guid.NewGuid().ToString() + "#domain.com>"));
ema.SendAndSaveCopy();
Also if you save the message first as a draft before sending it the server will assign the MessageId property which which should then be able to read back using Load.
Cheers
Glen
I can send message to all group in chat
return context.Clients.Group(sGrp).recieveNotification(message, user, chatid, uuid);
I can send message to all group in chat
return context.Clients.User(currentuser).seenyou(myname);
the problem when i send message to specific user in specific group
is there is way to do this .
The only way to send a message to a specific user is by addressing the user by its connection Id. In this case it doesn't matter if he is in a specific group or not. Other than that there's no such thing as a built-in list, that you can iterate on, you need to manage those references by yourself.
Of course, if the desired user is the sender, you can use Clients.Caller.
I have an email with yahoo business and MailKit works with POP. I want to download the message after finding a specific subject. Or could I use IMAP?
If the POP3 server supports the TOP extension, you can download just the message headers to first check the subject. To do that, you could do something like this:
if (client.Capabilities.HasFlag (Pop3Capabilities.Top)) {
var headers = client.GetMessageHeaders (index);
if (headers[HeaderId.Subject] == subject)
message = client.GetMessage (index);
}
If your Yahoo account also supports IMAP, I would recommend using IMAP since IMAP allows you to query the server for messages with a given subject which is much more efficient than downloading the headers for every message to check if the subject matches the one you are looking for.