Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Go sisimai compatibility 7e8a #314

Merged
merged 24 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0a455f7
Implement Sisimai::RFC1123
azumakuniyuki Oct 10, 2024
49fb385
Call Sisimai::RFC1123.is_validhostname to check the hostname picked f…
azumakuniyuki Oct 11, 2024
1d5a654
Require sisimai/address, sisimai/string
azumakuniyuki Oct 12, 2024
452cff5
Use Sisimai::RFC1123.is_validhostname() to check the hostname picked …
azumakuniyuki Oct 12, 2024
5e17bea
Code improvement for getting a Gmail state code
azumakuniyuki Oct 13, 2024
9578ade
Sisimai::Reason.get() renamed to find() for the compatibility with go…
azumakuniyuki Oct 13, 2024
74e41ff
Code improvement for getting error messages: import from https://gith…
azumakuniyuki Oct 15, 2024
381bd1a
Code improvement in Sisimai::Lhost::GoogleGroups
azumakuniyuki Oct 16, 2024
6e0f507
Code improvement for getting the original message
azumakuniyuki Oct 16, 2024
ba73296
Reduce and improve codes in Sisimai::Lhost::IMailServer
azumakuniyuki Oct 18, 2024
8e76574
Variable name changed
azumakuniyuki Oct 19, 2024
3feb2ff
Remove redundant condition, tiny code improvements
azumakuniyuki Oct 19, 2024
a00aca6
"f" is not being accessed from anywhere in Sisimai::Lhost::McAfee
azumakuniyuki Oct 22, 2024
e3dc357
Use Sisimai::String.aligned() for checking a recipient address
azumakuniyuki Oct 25, 2024
bfa57d1
Code improvement for getting an recipient address
azumakuniyuki Oct 25, 2024
e1e724e
Update the comment for commit bfa57d1a
azumakuniyuki Oct 25, 2024
0a27be1
Remove useless String#include?
azumakuniyuki Oct 29, 2024
97b5d9c
Fix error message patterns of "suspend" reason
azumakuniyuki Oct 30, 2024
0bb077a
Tiny code improvement
azumakuniyuki Oct 30, 2024
9575cc3
Code improvement for setting the last SMTP command
azumakuniyuki Oct 30, 2024
8d633e2
Code improvement for setting an error reason
azumakuniyuki Oct 30, 2024
e0953d0
Test fails only GitHub Actions
azumakuniyuki Nov 24, 2024
6844550
Disable the test in mail-test.rb:118, it fails GitHub Actions only
azumakuniyuki Nov 24, 2024
480bb2e
Test on GitHub Actions seems to wrong?
azumakuniyuki Nov 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions lib/sisimai/fact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Sisimai::Fact generate the list of decoded bounce data
class Fact
require 'sisimai/message'
require 'sisimai/rfc1123'
require 'sisimai/rfc1894'
require 'sisimai/rfc5322'
require 'sisimai/reason'
Expand Down Expand Up @@ -196,12 +197,28 @@
next unless piece['timestamp']

# OTHER_TEXT_HEADERS:
rr = mesg1['header']['received'] || []
unless rr.empty?
# Get a localhost and a remote host name from Received header.
piece['rhost'] = Sisimai::RFC5322.received(rr[-1])[1] if piece['rhost'].empty?
piece['lhost'] = '' if piece['rhost'] == piece['lhost']
piece['lhost'] = Sisimai::RFC5322.received(rr[ 0])[0] if piece['lhost'].empty?
recv = mesg1['header']['received'] || []
if piece['rhost'].empty?
# Try to pick a remote hostname from Received: headers of the bounce message
recv.reverse.each do |re|
# Check the Received: headers backwards and get a remote hostname
cv = Sisimai::RFC5322.received(re)[0]
next unless Sisimai::RFC1123.is_validhostname(cv)
piece['rhost'] = cv
break
end
end
piece['lhost'] = '' if piece['rhost'] == piece['lhost']

if piece['rhost'].empty?
# Try to pick a local hostname from Received: headers of the bounce message
recv.each do |le|
# Check the Received: headers backwards and get a local hostname
cv = Sisimai::RFC5322.received(le)[0]
next unless Sisimai::RFC1123.is_validhostname(cv)
piece['lhost'] = cv
break

Check warning on line 220 in lib/sisimai/fact.rb

View check run for this annotation

Codecov / codecov/patch

lib/sisimai/fact.rb#L219-L220

Added lines #L219 - L220 were not covered by tests
end
end

# Remove square brackets and curly brackets from the host variable
Expand Down Expand Up @@ -388,7 +405,7 @@
if thing['reason'].empty? || RetryIndex[thing['reason']]
# The value of "reason" is empty or is needed to check with other values again
re = thing['reason'].empty? ? 'undefined' : thing['reason']
thing['reason'] = Sisimai::Rhost.find(thing) || Sisimai::Reason.get(thing)
thing['reason'] = Sisimai::Rhost.find(thing) || Sisimai::Reason.find(thing)
thing['reason'] = re if thing['reason'].empty?
end

Expand Down
49 changes: 27 additions & 22 deletions lib/sisimai/lhost/gmail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ def inquire(mhead, mbody)
return nil unless mhead['from'].end_with?('<[email protected]>')
return nil unless mhead['subject'].start_with?('Delivery Status Notification')

require 'sisimai/address'
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
bodyslices = emailparts[0].split("\n")
Expand Down Expand Up @@ -204,43 +205,47 @@ def inquire(mhead, mbody)
end
return nil unless recipients > 0

require 'sisimai/string'
require 'sisimai/rfc1123'
dscontents.each do |e|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])

unless e['rhost']
if Sisimai::String.aligned(e['diagnosis'], [' by ', '. [', ']. '])
# Get the value of remote host
if Sisimai::String.aligned(e['diagnosis'], [' by ', '. [', ']. '])
# Google tried to deliver your message, but it was rejected by the server for the recipient
# domain example.jp by mx.example.jp. [192.0.2.153].
p1 = e['diagnosis'].rindex(' by ') || -1
p2 = e['diagnosis'].rindex('. [' ) || -1
hostname = e['diagnosis'][p1 + 4, p2 - p1 - 4]
ipv4addr = e['diagnosis'][p2 + 3, e['diagnosis'].rindex(']. ') - p2 - 3]
lastchar = hostname[-1, 1].upcase.ord
# Google tried to deliver your message, but it was rejected by the server for the recipient
# domain example.jp by mx.example.jp. [192.0.2.153].
p1 = e['diagnosis'].rindex(' by ') || -1
p2 = e['diagnosis'].rindex('. [' ) || -1
hostname = e['diagnosis'][p1 + 4, p2 - p1 - 4]
ipv4addr = e['diagnosis'][p2 + 3, e['diagnosis'].rindex(']. ') - p2 - 3]

e['rhost'] = hostname if lastchar > 64 && lastchar < 91
e['rhost'] ||= ipv4addr
end
e['rhost'] = hostname if Sisimai::RFC1123.is_validhostname(hostname)
e['rhost'] ||= ipv4addr
end

p1 = e['diagnosis'].rindex(' ') || -1
p2 = e['diagnosis'].rindex(')') || -1
statecode0 = e['diagnosis'][p1 + 1, p2 - p1 - 1] || 0
while true do
# Find "(state 18)" and pick "18" as a key of statetable
p1 = e['diagnosis'].rindex(' (state '); break unless p1
p2 = e['diagnosis'].rindex(')'); break unless p2
break if p1 > p2
cu = e['diagnosis'][p1 + 8, p2 - p1 - 8]
break if cu.empty?
break unless StateTable[cu]
e['reason'] = StateTable[cu]['reason']
e['command'] = StateTable[cu]['command']
break
end

if StateTable[statecode0]
# (state *)
e['reason'] = StateTable[statecode0]['reason']
e['command'] = StateTable[statecode0]['command']
else
# No state code
if e['reason'].nil?
# There is no no state code in the error message
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
next unless e['reason']
e['reason'] ||= ''; next if e['reason'].empty?

# Set pseudo status code
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis']) || ''
Expand Down
19 changes: 4 additions & 15 deletions lib/sisimai/lhost/gmx.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,10 @@ def inquire(mhead, mbody)
# host: mx.example.jp
v['rhost'] = e[6, e.size]
else
# Get error message
if Sisimai::SMTP::Status.find(e) || Sisimai::String.aligned(e, ['<', '@', '>'])
# 5.1.1 <[email protected]>... User Unknown
v['diagnosis'] ||= e
else
next if e.empty?
if e.start_with?('Reason:')
# Reason:
# delivery retry timeout exceeded
v['diagnosis'] = e

elsif v['diagnosis'] == 'Reason:'
v['diagnosis'] = e
end
end
# Get error messages
next if e.empty?
v['diagnosis'] ||= ''
v['diagnosis'] += e + ' '
end
end
return nil unless recipients > 0
Expand Down
14 changes: 7 additions & 7 deletions lib/sisimai/lhost/googlegroups.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ module Sisimai::Lhost
module GoogleGroups
class << self
require 'sisimai/lhost'

Indicators = Sisimai::Lhost.INDICATORS
Boundaries = ['----- Original message -----'].freeze
Boundaries = ['----- Original message -----', 'Content-Type: message/rfc822'].freeze

# @abstract Decodes the bounce message from Google Groups
# @param [Hash] mhead Message headers of a bounce email
Expand Down Expand Up @@ -39,7 +37,6 @@ def inquire(mhead, mbody)
# Google Groups
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
recordwide = { 'rhost' => '', 'reason' => '', 'diagnosis' => '' }
recipients = 0
v = dscontents[-1]

Expand All @@ -49,9 +46,12 @@ def inquire(mhead, mbody)
# * This group may not be open to posting.
entiremesg = emailparts[0].split(/\n\n/, 5).slice(0, 4).join(' ').tr("\n", ' ');
receivedby = mhead['received'] || []
recordwide['diagnosis'] = Sisimai::String.sweep(entiremesg)
recordwide['reason'] = emailparts[0].scan(/^[ ]?[*][ ]?/).size == 4 ? 'rejected' : 'onhold'
recordwide['rhost'] = Sisimai::RFC5322.received(receivedby[0])[1]
recordwide = {
'diagnosis' => Sisimai::String.sweep(entiremesg),
'reason' => 'onhold',
'rhost' => Sisimai::RFC5322.received(receivedby[0])[1],
}
recordwide['reason'] = 'rejected' if emailparts[0].scan(/^[ ]?[*][ ]?/).size == 4

mhead['x-failed-recipients'].split(',').each do |e|
# X-Failed-Recipients: [email protected], [email protected], ...
Expand Down
21 changes: 6 additions & 15 deletions lib/sisimai/lhost/imailserver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ class << self

Boundaries = ['Original message follows.'].freeze
StartingOf = { error: ['Body of message generated response:'] }.freeze
ReFailures = {
MessagesOf = {
'hostunknown' => ['Unknown host'],
'userunknown' => ['Unknown user', 'Invalid final delivery userid'],
'mailboxfull' => ['User mailbox exceeds allowed size'],
'virusdetected' => ['Requested action not taken: virus detected'],
'undefined' => ['undeliverable to'],
'spamdetected' => ['Blacklisted URL in message'],
'expired' => ['Delivery failed '],
}.freeze

Expand Down Expand Up @@ -45,24 +45,15 @@ def inquire(mhead, mbody)
v = dscontents[-1]

p0 = e.index(': ') || -1
if p0 > 8 && Sisimai::String.aligned(e, [': ', '@'])
if (p0 > 8 && Sisimai::String.aligned(e, [': ', '@'])) || e.start_with?('undeliverable ')
# Unknown user: [email protected]
if v['recipient']
# There are multiple recipient addresses in the message body.
dscontents << Sisimai::Lhost.DELIVERYSTATUS
v = dscontents[-1]
end
v['diagnosis'] = e
v['recipient'] = Sisimai::Address.s3s4(e[p0 + 2, e.size])
recipients += 1

elsif e.start_with?('undeliverable ')
# undeliverable to [email protected]
if v['recipient']
# There are multiple recipient addresses in the message body.
dscontents << Sisimai::Lhost.DELIVERYSTATUS
v = dscontents[-1]
end
v['diagnosis'] = e
v['recipient'] = Sisimai::Address.s3s4(e)
recipients += 1
else
Expand All @@ -88,9 +79,9 @@ def inquire(mhead, mbody)
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
e['command'] = Sisimai::SMTP::Command.find(e['diagnosis'])

ReFailures.each_key do |r|
MessagesOf.each_key do |r|
# Verify each regular expression of session errors
next unless ReFailures[r].any? { |a| e['diagnosis'].include?(a) }
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
e['reason'] = r
break
end
Expand Down
4 changes: 2 additions & 2 deletions lib/sisimai/lhost/kddi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class << self

Indicators = Sisimai::Lhost.INDICATORS
Boundaries = ['Content-Type: message/rfc822'].freeze
MarkingsOf = { message: ['Your mail sent on:', 'Your mail attempted to be delivered on:'] }.freeze
StartingOf = { message: ['Your mail sent on:', 'Your mail attempted to be delivered on:'] }.freeze
MessagesOf = {
'mailboxfull' => ['As their mailbox is full'],
'norelaying' => ['Due to the following SMTP relay error'],
Expand Down Expand Up @@ -40,7 +40,7 @@ def inquire(mhead, mbody)
# line of the beginning of the original message.
if readcursor == 0
# Beginning of the bounce message or delivery status part
readcursor |= Indicators[:deliverystatus] if MarkingsOf[:message].any? { |a| e.start_with?(a) }
readcursor |= Indicators[:deliverystatus] if StartingOf[:message].any? { |a| e.start_with?(a) }
next
end
next if (readcursor & Indicators[:deliverystatus]) == 0
Expand Down
5 changes: 1 addition & 4 deletions lib/sisimai/lhost/mailfoundry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,14 @@ def inquire(mhead, mbody)
v['recipient'] = e[e.index('<'), e.size]
recipients += 1
else
# Error message
# Error messages
if e == StartingOf[:error][0]
# Delivery failed for the following reason:
v['diagnosis'] = e
else
# Detect error message
next if e.empty?
next if v['diagnosis'].nil? || v['diagnosis'].empty?
next if e.start_with?('-')

# Server mx22.example.org[192.0.2.222] failed with: 550 <[email protected]> No such user here
v['diagnosis'] << ' ' << e
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/sisimai/lhost/mcafee.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def inquire(mhead, mbody)
issuedcode = e[e.index('(') + 1, e.size]
recipients += 1

elsif f = Sisimai::RFC1894.match(e)
elsif Sisimai::RFC1894.match(e)
# "e" matched with any field defined in RFC3464
o = Sisimai::RFC1894.field(e)
unless o
Expand Down
17 changes: 9 additions & 8 deletions lib/sisimai/lhost/messagingserver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,21 @@ def inquire(mhead, mbody)
# 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 e.start_with?(' Recipient address: ') && e.index('@') > 1
# Recipient address: [email protected]
if v['recipient']
if Sisimai::String.aligned(e, [' Recipient address: ', '@', '.']) ||
Sisimai::String.aligned(e, [' Original address: ', '@', '.'])
# Recipient address: @smtp.example.net:kijitora@server
# Original address: [email protected]
cv = Sisimai::Address.s3s4(e[e.rindex(' ') + 1, e.size])
next unless Sisimai::Address.is_emailaddress(cv)

if v['recipient'] && cv != v['recipient']
# There are multiple recipient addresses in the message body.
dscontents << Sisimai::Lhost.DELIVERYSTATUS
v = dscontents[-1]
end
v['recipient'] = Sisimai::Address.s3s4(e[e.rindex(' ') + 1, e.size])
v['recipient'] = cv
recipients += 1

elsif e.start_with?(' Original address: ') && e.index('@') > 1
# Original address: [email protected]
v['recipient'] = Sisimai::Address.s3s4(e[e.rindex(' ') + 1, e.size])

elsif e.start_with?(' Date: ')
# Date: Fri, 21 Nov 2014 23:34:45 +0900
v['date'] = e[e.index(':') + 2, e.size]
Expand Down
2 changes: 1 addition & 1 deletion lib/sisimai/lhost/opensmtpd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def inquire(mhead, mbody)
# Below is a copy of the original message:
v = dscontents[-1]

if e.include?('@') && Sisimai::String.aligned(e, ['@', ' '])
if Sisimai::String.aligned(e, ['@', ' '])
# [email protected]: 550 5.2.2 <kijitora@example>... Mailbox Full
if v['recipient']
# There are multiple recipient addresses in the message body.
Expand Down
Loading