简体   繁体   中英

How detect send email failure on Exchange C#

I am trying to detect whether the email sent by my application had a failure delivery. This means I am not trying to validate the email but actually just if it reached the destination mailbox.

Here's the .Net Framework application code that I am using:

    public void Send(EmailRequest emailRequest)
    {
        // Creates the message itselft
        EmailMessage message = new EmailMessage(ServiceExchange);
        message.Body = new MessageBody(emailRequest.Message);
        message.Subject = emailRequest.Subject;
        message.ToRecipients.Add(emailRequest.To);

        // Create a custom extended property and add it to the message. 
        Guid myPropertySetId = Guid.NewGuid();
        ExtendedPropertyDefinition myExtendedPropertyDefinition = new ExtendedPropertyDefinition(myPropertySetId, "MyExtendedPropertyName", MapiPropertyType.String);
        message.SetExtendedProperty(myExtendedPropertyDefinition, "MyExtendedPropertyValue");

        // Asynchronously, call
        message.SendAndSaveCopy();

        // Wait one second (while EWS sends and saves the message). 
        System.Threading.Thread.Sleep(1000);

        // Now, find the saved copy of the message by using the custom extended property. 
        ItemView view = new ItemView(5);
        SearchFilter searchFilter = new SearchFilter.IsEqualTo(myExtendedPropertyDefinition, "MyExtendedPropertyValue");
        view.PropertySet = new PropertySet(BasePropertySet.IdOnly, ItemSchema.Subject, myExtendedPropertyDefinition);
        FindItemsResults<Item> findResults = ServiceExchange.FindItems(WellKnownFolderName.SentItems, searchFilter, view);

        if (findResults == null) throw new Exception("Could not find results - findResults is null");
        if (findResults.Items == null) throw new Exception("Could not find results - findResults.Items is null");
        if (findResults.Items.Count == 0) throw new Exception("Could not find results - findResults.Items is 0");
        if (findResults.Items.Count > 1) throw new Exception("findResults items returned more than one result");

        ItemId itemID = null;

        // TODO change this to single line
        // Process results and retrieve the email item ID (unique)
        foreach (Item myItem in findResults.Items)
        {
            if (myItem is EmailMessage)
            {
                EmailMessage em = myItem as EmailMessage;
                itemID = em.Id;
                //Console.WriteLine(em.Subject);
                //Console.WriteLine(em.Id.UniqueId);
            }
        }

        // TODO: ANY WAY TO RETRIEVE EMAIL FAILURE?

    }   

For example: If I send this to a valid email everything is fine. The goal here is to detect failures so that we can contact business and check why we have a bad email address stored.

Thanks!

If the email address that you have on file is invalid, SendAndSaveCopy() should throw an exception stating as much. You could implement a try/catch statement to detect any failures, and send the failures to a logger, which would give you a text list to work with:

public void Send(EmailRequest emailRequest)
{
    try
    {
        // Creates the message itselft
        EmailMessage message = new EmailMessage(ServiceExchange);
        message.Body = new MessageBody(emailRequest.Message);
        message.Subject = emailRequest.Subject;
        message.ToRecipients.Add(emailRequest.To);

        // Create a custom extended property and add it to the message. 
        Guid myPropertySetId = Guid.NewGuid();
        ExtendedPropertyDefinition myExtendedPropertyDefinition = new ExtendedPropertyDefinition(myPropertySetId, "MyExtendedPropertyName", MapiPropertyType.String);
        message.SetExtendedProperty(myExtendedPropertyDefinition, "MyExtendedPropertyValue");

        // Asynchronously, call
        message.SendAndSaveCopy();

        // Wait one second (while EWS sends and saves the message). 
        System.Threading.Thread.Sleep(1000);
    }
    catch (Exception x)
    {
        logger.LogError(x.Message);

    }
}

You can find other examples here .

I am trying to detect whether the email sent by my application had a failure delivery. This means I am not trying to validate the email but actually just if it reached the destination mailbox.

Once you hand off the message to Exchange, it might not even go out immediately. Once Exchange attempts to send it, it may discover that the remote server is unavailable and will then retry later.

Eventually, Exchange will either get the remote server to accept the message or it will give up.

If the remote server accepts the message, you can get a send receipt if you configure the flag in your message. However this does not mean that the message was actually delivered to the recipient or that the recipient read it; it only means that Exchange was able to give it to the destination server.

Many servers simply accept and discard mail sent to a non-existent user. Others toss them into a global "spam" folder.

If you set the correct "reply-to" address in your message, you will get an email from Exchange if the message cannot be delivered to the remote server within the timeout that the Exchange admin has set. This it typically a couple of days.

However even if you set the "Read receipt" flag, it's entirely possible for the recipient to read the message and not send it. Compliance is voluntary.

The really, really short answer is "you can detect immediate failures, but can't actually be sure that the message has been read or delivered", and in any case it can't happen in your code.

If it's helpful, there are a few errors that can be detected immediately, and these will show up in your try/catch block, but these are the exception rather than the rule.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM