module Sisimai::Lhost::Verizon
Sisimai::Lhost::Verizon
parses a bounce email which created by Verizon
Wireless. Methods in the module are called from only Sisimai::Message
.
Constants
- Indicators
Public Class Methods
description()
click to toggle source
# File lib/sisimai/lhost/verizon.rb, line 160 def description; return 'Verizon Wireless: https://www.verizonwireless.com'; end
make(mhead, mbody)
click to toggle source
Parse bounce messages from Verizon
@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/verizon.rb, line 16 def make(mhead, mbody) match = -1 while true # Check the value of "From" header # :'subject' => %r/Undeliverable Message/, break unless mhead['received'].any? { |a| a.include?('.vtext.com (') } match = 1 if mhead['from'] == 'post_master@vtext.com' match = 0 if mhead['from'] =~ /[<]?sysadmin[@].+[.]vzwpix[.]com[>]?\z/ break end return nil if match < 0 dscontents = [Sisimai::Lhost.DELIVERYSTATUS] rebackbone = /^__BOUNDARY_STRING_HERE__/ readcursor = 0 # (Integer) Points the current cursor position recipients = 0 # (Integer) The number of 'Final-Recipient' header senderaddr = '' # (String) Sender address in the message body subjecttxt = '' # (String) Subject of the original message markingsof = {} # (Hash) Delimiter patterns startingof = {} # (Hash) Delimiter strings messagesof = {} # (Hash) Error message patterns v = nil if match == 1 # vtext.com markingsof = { message: %r/\AError:[ \t]/ } messagesof = { # The attempted recipient address does not exist. 'userunknown' => ['550 - Requested action not taken: no such user here'], } boundary00 = Sisimai::MIME.boundary(mhead['content-type'], 1) || '' rebackbone = Regexp.new('^' << Regexp.escape(boundary00)) unless boundary00.empty? emailsteak = Sisimai::RFC5322.fillet(mbody, rebackbone) bodyslices = emailsteak[0].split("\n") 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 =~ markingsof[:message] next end next if (readcursor & Indicators[:deliverystatus]) == 0 next if e.empty? # Message details: # Subject: Test message # Sent date: Wed Jun 12 02:21:53 GMT 2013 # MAIL FROM: *******@hg.example.com # RCPT TO: *****@vtext.com v = dscontents[-1] if cv = e.match(/\A[ \t]+RCPT TO: (.*)\z/) if v['recipient'] # There are multiple recipient addresses in the message body. dscontents << Sisimai::Lhost.DELIVERYSTATUS v = dscontents[-1] end v['recipient'] = cv[1] recipients += 1 next elsif cv = e.match(/\A[ \t]+MAIL FROM:[ \t](.+)\z/) # MAIL FROM: *******@hg.example.com senderaddr = cv[1] if senderaddr.empty? elsif cv = e.match(/\A[ \t]+Subject:[ \t](.+)\z/) # Subject: subjecttxt = cv[1] if subjecttxt.empty? else # 550 - Requested action not taken: no such user here v['diagnosis'] = e if e =~ /\A(\d{3})[ \t][-][ \t](.*)\z/ end end else # vzwpix.com startingof = { message: ['Message could not be delivered to mobile'] } messagesof = { 'userunknown' => ['No valid recipients for this MM'] } boundary00 = Sisimai::MIME.boundary(mhead['content-type'], 1) rebackbone = Regexp.new('^' << Regexp.escape(boundary00)) unless boundary00.empty? emailsteak = Sisimai::RFC5322.fillet(mbody, rebackbone) bodyslices = emailsteak[0].split("\n") 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? # Original Message: # From: kijitora <kijitora@example.jp> # To: 0000000000@vzwpix.com # Subject: test for bounce # Date: Wed, 20 Jun 2013 10:29:52 +0000 v = dscontents[-1] if cv = e.match(/\ATo:[ \t]+(.*)\z/) 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 next elsif cv = e.match(/\AFrom:[ \t](.+)\z/) # From: kijitora <kijitora@example.jp> senderaddr = Sisimai::Address.s3s4(cv[1]) if senderaddr.empty? elsif cv = e.match(/\ASubject:[ \t](.+)\z/) # Subject: subjecttxt = cv[1] if subjecttxt.empty? else # Message could not be delivered to mobile. # Error: No valid recipients for this MM v['diagnosis'] = e if e =~ /\AError:[ \t]+(.+)\z/ end end end return nil unless recipients > 0 # Set the value of "MAIL FROM:" and "From:" emailsteak[1] << ('From: ' << senderaddr << "\n") unless emailsteak[1] =~ /^From: / emailsteak[1] << ('Subject: ' << subjecttxt << "\n") unless emailsteak[1] =~ /^Subject: / 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