module Sisimai::Lhost::MessagingServer
Sisimai::Lhost::MessagingServer
parses a bounce email which created by Oracle Communications Messaging Server and Sun Java System Messaging Server. Methods in the module are called from only Sisimai::Message
.
Constants
- Indicators
- MessagesOf
- ReBackbone
- StartingOf
Public Class Methods
description()
click to toggle source
# File lib/sisimai/lhost/messagingserver.rb, line 148 def description; return 'Oracle Communications Messaging Server'; end
make(mhead, mbody)
click to toggle source
Parse bounce messages from MessagingServer
@param [Hash] mhead Message
headers of a bounce email @param [String] mbody Message
body of a bounce email @return [Hash] Bounce data list and message/rfc822 part @return [Nil] it failed to parse or the arguments are missing
# File lib/sisimai/lhost/messagingserver.rb, line 20 def make(mhead, mbody) # :received => %r/[ ][(]MessagingServer[)][ ]with[ ]/, match = 0 match += 1 if mhead['content-type'].include?('Boundary_(ID_') match += 1 if mhead['subject'].start_with?('Delivery Notification: ') return nil unless match > 0 dscontents = [Sisimai::Lhost.DELIVERYSTATUS] emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone) bodyslices = emailsteak[0].split("\n") readcursor = 0 # (Integer) Points the current cursor position recipients = 0 # (Integer) The number of 'Final-Recipient' header v = nil while e = bodyslices.shift do # Read error messages and delivery status lines from the head of the email # to the previous line of the beginning of the original message. if readcursor == 0 # Beginning of the bounce message or delivery status part readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0]) next end next if (readcursor & Indicators[:deliverystatus]) == 0 next if e.empty? # --Boundary_(ID_0000000000000000000000) # Content-type: text/plain; charset=us-ascii # Content-language: en-US # # This report relates to a message you sent with the following header fields: # # Message-id: <CD8C6134-C312-41D5-B083-366F7FA1D752@me.example.com> # Date: Fri, 21 Nov 2014 23:34:45 +0900 # From: Shironeko <shironeko@me.example.com> # To: kijitora@example.jp # Subject: Nyaaaaaaaaaaaaaaaaaaaaaan # # Your message cannot be delivered to the following recipients: # # Recipient address: kijitora@example.jp # Reason: Remote SMTP server has rejected address # Diagnostic code: smtp;550 5.1.1 <kijitora@example.jp>... User Unknown # Remote system: dns;mx.example.jp (TCP|17.111.174.67|47323|192.0.2.225|25) (6jo.example.jp ESMTP SENDMAIL-VM) v = dscontents[-1] if cv = e.match(/\A[ \t]+Recipient address:[ \t]*([^ ]+[@][^ ]+)\z/) # Recipient address: kijitora@example.jp if v['recipient'] # There are multiple recipient addresses in the message body. dscontents << Sisimai::Lhost.DELIVERYSTATUS v = dscontents[-1] end v['recipient'] = Sisimai::Address.s3s4(cv[1]) recipients += 1 elsif cv = e.match(/\A[ \t]+Original address:[ \t]*([^ ]+[@][^ ]+)\z/) # Original address: kijitora@example.jp v['recipient'] = Sisimai::Address.s3s4(cv[1]) elsif cv = e.match(/\A[ \t]+Date:[ \t]*(.+)\z/) # Date: Fri, 21 Nov 2014 23:34:45 +0900 v['date'] = cv[1] elsif cv = e.match(/\A[ \t]+Reason:[ \t]*(.+)\z/) # Reason: Remote SMTP server has rejected address v['diagnosis'] = cv[1] elsif cv = e.match(/\A[ \t]+Diagnostic code:[ \t]*([^ ]+);(.+)\z/) # Diagnostic code: smtp;550 5.1.1 <kijitora@example.jp>... User Unknown v['spec'] = cv[1].upcase v['diagnosis'] = cv[2] elsif cv = e.match(/\A[ \t]+Remote system:[ ]*dns;([^ ]+)[ ]*([^ ]+)[ ]*.+\z/) # Remote system: dns;mx.example.jp (TCP|17.111.174.67|47323|192.0.2.225|25) # (6jo.example.jp ESMTP SENDMAIL-VM) remotehost = cv[1] # remote host sessionlog = cv[2] # smtp session v['rhost'] = remotehost # The value does not include ".", use IP address instead. # (TCP|17.111.174.67|47323|192.0.2.225|25) next unless cv = sessionlog.match(/\A[(]TCP|(.+)|\d+|(.+)|\d+[)]/) v['lhost'] = cv[1] v['rhost'] = cv[2] unless remotehost =~ /[^.]+[.][^.]+/ else # Original-envelope-id: 0NFC009FLKOUVMA0@mr21p30im-asmtp004.me.com # Reporting-MTA: dns;mr21p30im-asmtp004.me.com (tcp-daemon) # Arrival-date: Thu, 29 Apr 2014 23:34:45 +0000 (GMT) # # Original-recipient: rfc822;kijitora@example.jp # Final-recipient: rfc822;kijitora@example.jp # Action: failed # Status: 5.1.1 (Remote SMTP server has rejected address) # Remote-MTA: dns;mx.example.jp (TCP|17.111.174.67|47323|192.0.2.225|25) # (6jo.example.jp ESMTP SENDMAIL-VM) # Diagnostic-code: smtp;550 5.1.1 <kijitora@example.jp>... User Unknown # if cv = e.match(/\AStatus:[ ]*(\d[.]\d[.]\d)[ ]*[(](.+)[)]\z/) # Status: 5.1.1 (Remote SMTP server has rejected address) v['status'] = cv[1] v['diagnosis'] ||= cv[2] elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/) # Arrival-date: Thu, 29 Apr 2014 23:34:45 +0000 (GMT) v['date'] ||= cv[1] elsif cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/) # Reporting-MTA: dns;mr21p30im-asmtp004.me.com (tcp-daemon) localhost = cv[1] v['lhost'] ||= localhost v['lhost'] = localhost unless v['lhost'] =~ /[^.]+[.][^ ]+/ end end end return nil unless recipients > 0 dscontents.each do |e| e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) MessagesOf.each_key do |r| # Verify each regular expression of session errors next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) } e['reason'] = r break end end return { 'ds' => dscontents, 'rfc822' => emailsteak[1] } end