示例#1
0
        /// <summary>
        /// Examines an email to try to identify detailed bounce information from it.
        /// </summary>
        /// <param name="filename">Path and filename of the file being processed.</param>
        /// <param name="message">The entire text content for an email (headers and body).</param>
        /// <returns>An EmailProcessingResult value indicating whether the the email was
        /// successfully processed or not.</returns>
        public EmailProcessingDetails ProcessBounceEmail(string message)
        {
            EmailProcessingDetails bounceDetails = new EmailProcessingDetails();

            MimeMessage msg = MimeMessage.Parse(message);

            if (msg == null)
            {
                bounceDetails.ProcessingResult = EmailProcessingResult.ErrorContent;
                bounceDetails.BounceIdentifier = Core.Enums.BounceIdentifier.NotIdentifiedAsABounce;
                return(bounceDetails);
            }


            // "x-receiver" should contain what Manta originally set as the "return-path" when sending.
            MessageHeader returnPath = msg.Headers.GetFirstOrDefault("x-receiver");

            if (returnPath == null)
            {
                bounceDetails.ProcessingResult = EmailProcessingResult.ErrorNoReturnPath;
                bounceDetails.BounceIdentifier = Core.Enums.BounceIdentifier.UnknownReturnPath;
                return(bounceDetails);
            }

            string rcptTo         = string.Empty;
            int    internalSendID = 0;

            if (!ReturnPathManager.TryDecode(returnPath.Value, out rcptTo, out internalSendID))
            {
                // Not a valid Return-Path so can't process.
                bounceDetails.ProcessingResult = EmailProcessingResult.ErrorNoReturnPath;
                bounceDetails.BounceIdentifier = Core.Enums.BounceIdentifier.UnknownReturnPath;
                return(bounceDetails);
            }

            MantaBounceEvent bounceEvent = new MantaBounceEvent();

            bounceEvent.EmailAddress = rcptTo;
            bounceEvent.SendID       = MantaMTA.Core.DAL.SendDB.GetSend(internalSendID).ID;

            // TODO: Might be good to get the DateTime found in the email.
            bounceEvent.EventTime = DateTime.UtcNow;

            // These properties are both set according to the SMTP code we find, if any.
            bounceEvent.BounceInfo.BounceCode = MantaBounceCode.Unknown;
            bounceEvent.BounceInfo.BounceType = MantaBounceType.Unknown;
            bounceEvent.EventType             = MantaEventType.Bounce;

            // First, try to find a NonDeliveryReport body part as that's the proper way for an MTA
            // to tell us there was an issue sending the email.

            BouncePair bouncePair;
            string     bounceMsg;
            BodyPart   deliveryReportBodyPart;
            string     deliveryReport = string.Empty;

            if (FindFirstBodyPartByMediaType(msg.BodyParts, "message/delivery-status", out deliveryReportBodyPart))
            {
                // If we've got a delivery report, check it for info.

                // Abuse report content may have long lines whitespace folded.
                deliveryReport = MimeMessage.UnfoldHeaders(deliveryReportBodyPart.GetDecodedBody());

                if (ParseNdr(deliveryReport, out bouncePair, out bounceMsg, out bounceDetails))
                {
                    // Successfully parsed.
                    bounceEvent.BounceInfo = bouncePair;
                    bounceEvent.Message    = bounceMsg;

                    // Write BounceEvent to DB.
                    Save(bounceEvent);

                    bounceDetails.ProcessingResult = EmailProcessingResult.SuccessBounce;
                    return(bounceDetails);
                }
            }



            // We're still here so there was either no NDR part or nothing contained within it that we could
            // interpret so have to check _all_ body parts for something useful.
            if (FindBounceReason(msg.BodyParts, out bouncePair, out bounceMsg, out bounceDetails))
            {
                bounceEvent.BounceInfo = bouncePair;
                bounceEvent.Message    = bounceMsg;

                // Write BounceEvent to DB.
                Save(bounceEvent);

                bounceDetails.ProcessingResult = EmailProcessingResult.SuccessBounce;
                return(bounceDetails);
            }



            // Nope - no clues relating to why the bounce occurred.
            bounceEvent.BounceInfo.BounceType = MantaBounceType.Unknown;
            bounceEvent.BounceInfo.BounceCode = MantaBounceCode.Unknown;
            bounceEvent.Message = string.Empty;

            bounceDetails.BounceIdentifier = Core.Enums.BounceIdentifier.NotIdentifiedAsABounce;
            bounceDetails.ProcessingResult = EmailProcessingResult.Unknown;
            return(bounceDetails);
        }
示例#2
0
        /// <summary>
        /// Examines an SMTP response message to identify detailed bounce information from it.
        /// </summary>
        /// <param name="response">The message that's come back from an external MTA when attempting to send an email.</param>
        /// <param name="rcptTo">The email address that was being sent to.</param>
        /// <param name="internalSendID">The internal Manta SendID.</param>
        /// <returns>True if a bounce was found and recorded, false if not.</returns>
        internal bool ProcessSmtpResponseMessage(string response, string rcptTo, int internalSendID, out EmailProcessingDetails bounceIdentification)
        {
            bounceIdentification = new EmailProcessingDetails();



            // Check for TimedOutInQueue message first.
            if (response.Equals(MtaParameters.TIMED_OUT_IN_QUEUE_MESSAGE, StringComparison.OrdinalIgnoreCase))
            {
                bounceIdentification = null;

                MantaTimedOutInQueueEvent timeOut = new MantaTimedOutInQueueEvent
                {
                    EventType    = MantaEventType.TimedOutInQueue,
                    EmailAddress = rcptTo,
                    SendID       = SendDB.GetSend(internalSendID).ID,
                    EventTime    = DateTime.UtcNow
                };

                // Log to DB.
                Save(timeOut);

                // All done return true.
                return(true);
            }



            BouncePair bouncePair    = new BouncePair();
            string     bounceMessage = string.Empty;


            if (ParseBounceMessage(response, out bouncePair, out bounceMessage, out bounceIdentification))
            {
                // Were able to find the bounce so create the bounce event.
                MantaBounceEvent bounceEvent = new MantaBounceEvent
                {
                    EventType    = MantaEventType.Bounce,
                    EmailAddress = rcptTo,
                    BounceInfo   = bouncePair,
                    SendID       = SendDB.GetSend(internalSendID).ID,
                    // It is possible that the bounce was generated a while back, but we're assuming "now" for the moment.
                    // Might be good to get the DateTime found in the email at a later point.
                    EventTime = DateTime.UtcNow,
                    Message   = response
                };

                // Log to DB.
                Save(bounceEvent);


                // All done return true.
                return(true);
            }



            // Couldn't identify the bounce.

            bounceIdentification.BounceIdentifier = Core.Enums.BounceIdentifier.NotIdentifiedAsABounce;

            return(false);
        }