Refactoring of email detection (added also tests now).
This commit is contained in:
parent
882d1cd5aa
commit
7070b1748c
8 changed files with 1611 additions and 709 deletions
|
@ -193,415 +193,11 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
|
||||||
# check admin permissions
|
# check admin permissions
|
||||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||||
|
|
||||||
# validation
|
# probe settings based on email and password
|
||||||
user = nil
|
render json: EmailHelper::Probe.full(
|
||||||
domain = nil
|
email: params[:email],
|
||||||
if params[:email] =~ /^(.+?)@(.+?)$/
|
password: params[:password],
|
||||||
user = $1
|
)
|
||||||
domain = $2
|
|
||||||
end
|
|
||||||
|
|
||||||
if !user || !domain
|
|
||||||
render json: {
|
|
||||||
result: 'invalid',
|
|
||||||
messages: {
|
|
||||||
email: 'Invalid email.'
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
# check domain based attributes
|
|
||||||
provider_map = {
|
|
||||||
google: {
|
|
||||||
domain: 'gmail.com|googlemail.com|gmail.de',
|
|
||||||
inbound: {
|
|
||||||
adapter: 'imap',
|
|
||||||
options: {
|
|
||||||
host: 'imap.gmail.com',
|
|
||||||
port: '993',
|
|
||||||
ssl: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
outbound: {
|
|
||||||
adapter: 'smtp',
|
|
||||||
options: {
|
|
||||||
host: 'smtp.gmail.com',
|
|
||||||
port: '25',
|
|
||||||
start_tls: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
microsoft: {
|
|
||||||
domain: 'outlook.com|hotmail.com',
|
|
||||||
inbound: {
|
|
||||||
adapter: 'imap',
|
|
||||||
options: {
|
|
||||||
host: 'imap-mail.outlook.com',
|
|
||||||
port: '993',
|
|
||||||
ssl: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
outbound: {
|
|
||||||
adapter: 'smtp',
|
|
||||||
options: {
|
|
||||||
host: 'smtp-mail.outlook.com',
|
|
||||||
port: 25,
|
|
||||||
start_tls: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
# probe based on email domain and mx
|
|
||||||
domains = [domain]
|
|
||||||
mail_exchangers = mxers(domain)
|
|
||||||
if mail_exchangers && mail_exchangers[0]
|
|
||||||
logger.info "MX for #{domain}: #{mail_exchangers} - #{mail_exchangers[0][0]}"
|
|
||||||
end
|
|
||||||
if mail_exchangers && mail_exchangers[0] && mail_exchangers[0][0]
|
|
||||||
domains.push mail_exchangers[0][0]
|
|
||||||
end
|
|
||||||
provider_map.each {|_provider, settings|
|
|
||||||
domains.each {|domain_to_check|
|
|
||||||
|
|
||||||
next if domain_to_check !~ /#{settings[:domain]}/i
|
|
||||||
|
|
||||||
# probe inbound
|
|
||||||
result = email_probe_inbound( settings[:inbound] )
|
|
||||||
if result[:result] != 'ok'
|
|
||||||
render json: result
|
|
||||||
return # rubocop:disable Lint/NonLocalExitFromIterator
|
|
||||||
end
|
|
||||||
|
|
||||||
# probe outbound
|
|
||||||
result = email_probe_outbound( settings[:outbound], params[:email] )
|
|
||||||
if result[:result] != 'ok'
|
|
||||||
render json: result
|
|
||||||
return # rubocop:disable Lint/NonLocalExitFromIterator
|
|
||||||
end
|
|
||||||
|
|
||||||
render json: {
|
|
||||||
result: 'ok',
|
|
||||||
setting: settings,
|
|
||||||
}
|
|
||||||
return # rubocop:disable Lint/NonLocalExitFromIterator
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# probe inbound
|
|
||||||
inbound_map = []
|
|
||||||
if mail_exchangers && mail_exchangers[0] && mail_exchangers[0][0]
|
|
||||||
inbound_mx = [
|
|
||||||
{
|
|
||||||
adapter: 'imap',
|
|
||||||
options: {
|
|
||||||
host: mail_exchangers[0][0],
|
|
||||||
port: 993,
|
|
||||||
ssl: true,
|
|
||||||
user: user,
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'imap',
|
|
||||||
options: {
|
|
||||||
host: mail_exchangers[0][0],
|
|
||||||
port: 993,
|
|
||||||
ssl: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
inbound_map = inbound_map + inbound_mx
|
|
||||||
end
|
|
||||||
inbound_auto = [
|
|
||||||
{
|
|
||||||
adapter: 'imap',
|
|
||||||
options: {
|
|
||||||
host: "mail.#{domain}",
|
|
||||||
port: 993,
|
|
||||||
ssl: true,
|
|
||||||
user: user,
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'imap',
|
|
||||||
options: {
|
|
||||||
host: "mail.#{domain}",
|
|
||||||
port: 993,
|
|
||||||
ssl: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'imap',
|
|
||||||
options: {
|
|
||||||
host: "imap.#{domain}",
|
|
||||||
port: 993,
|
|
||||||
ssl: true,
|
|
||||||
user: user,
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'imap',
|
|
||||||
options: {
|
|
||||||
host: "imap.#{domain}",
|
|
||||||
port: 993,
|
|
||||||
ssl: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'pop3',
|
|
||||||
options: {
|
|
||||||
host: "mail.#{domain}",
|
|
||||||
port: 995,
|
|
||||||
ssl: true,
|
|
||||||
user: user,
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'pop3',
|
|
||||||
options: {
|
|
||||||
host: "mail.#{domain}",
|
|
||||||
port: 995,
|
|
||||||
ssl: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'pop3',
|
|
||||||
options: {
|
|
||||||
host: "pop.#{domain}",
|
|
||||||
port: 995,
|
|
||||||
ssl: true,
|
|
||||||
user: user,
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'pop3',
|
|
||||||
options: {
|
|
||||||
host: "pop.#{domain}",
|
|
||||||
port: 995,
|
|
||||||
ssl: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'pop3',
|
|
||||||
options: {
|
|
||||||
host: "pop3.#{domain}",
|
|
||||||
port: 995,
|
|
||||||
ssl: true,
|
|
||||||
user: user,
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'pop3',
|
|
||||||
options: {
|
|
||||||
host: "pop3.#{domain}",
|
|
||||||
port: 995,
|
|
||||||
ssl: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
inbound_map = inbound_map + inbound_auto
|
|
||||||
settings = {}
|
|
||||||
success = false
|
|
||||||
inbound_map.each {|config|
|
|
||||||
logger.info "INBOUND PROBE: #{config.inspect}"
|
|
||||||
result = email_probe_inbound( config )
|
|
||||||
logger.info "INBOUND RESULT: #{result.inspect}"
|
|
||||||
|
|
||||||
next if result[:result] != 'ok'
|
|
||||||
|
|
||||||
success = true
|
|
||||||
settings[:inbound] = config
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if !success
|
|
||||||
render json: {
|
|
||||||
result: 'failed',
|
|
||||||
}
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
# probe outbound
|
|
||||||
outbound_map = []
|
|
||||||
if mail_exchangers && mail_exchangers[0] && mail_exchangers[0][0]
|
|
||||||
outbound_mx = [
|
|
||||||
{
|
|
||||||
adapter: 'smtp',
|
|
||||||
options: {
|
|
||||||
host: mail_exchangers[0][0],
|
|
||||||
port: 25,
|
|
||||||
start_tls: true,
|
|
||||||
user: user,
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'smtp',
|
|
||||||
options: {
|
|
||||||
host: mail_exchangers[0][0],
|
|
||||||
port: 25,
|
|
||||||
start_tls: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'smtp',
|
|
||||||
options: {
|
|
||||||
host: mail_exchangers[0][0],
|
|
||||||
port: 465,
|
|
||||||
start_tls: true,
|
|
||||||
user: user,
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'smtp',
|
|
||||||
options: {
|
|
||||||
host: mail_exchangers[0][0],
|
|
||||||
port: 465,
|
|
||||||
start_tls: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
outbound_map = outbound_map + outbound_mx
|
|
||||||
end
|
|
||||||
outbound_auto = [
|
|
||||||
{
|
|
||||||
adapter: 'smtp',
|
|
||||||
options: {
|
|
||||||
host: "mail.#{domain}",
|
|
||||||
port: 25,
|
|
||||||
start_tls: true,
|
|
||||||
user: user,
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'smtp',
|
|
||||||
options: {
|
|
||||||
host: "mail.#{domain}",
|
|
||||||
port: 25,
|
|
||||||
start_tls: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'smtp',
|
|
||||||
options: {
|
|
||||||
host: "mail.#{domain}",
|
|
||||||
port: 465,
|
|
||||||
start_tls: true,
|
|
||||||
user: user,
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'smtp',
|
|
||||||
options: {
|
|
||||||
host: "mail.#{domain}",
|
|
||||||
port: 465,
|
|
||||||
start_tls: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'smtp',
|
|
||||||
options: {
|
|
||||||
host: "smtp.#{domain}",
|
|
||||||
port: 25,
|
|
||||||
start_tls: true,
|
|
||||||
user: user,
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'smtp',
|
|
||||||
options: {
|
|
||||||
host: "smtp.#{domain}",
|
|
||||||
port: 25,
|
|
||||||
start_tls: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'smtp',
|
|
||||||
options: {
|
|
||||||
host: "smtp.#{domain}",
|
|
||||||
port: 465,
|
|
||||||
start_tls: true,
|
|
||||||
user: user,
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
adapter: 'smtp',
|
|
||||||
options: {
|
|
||||||
host: "smtp.#{domain}",
|
|
||||||
port: 465,
|
|
||||||
start_tls: true,
|
|
||||||
user: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
success = false
|
|
||||||
outbound_map.each {|config|
|
|
||||||
logger.info "OUTBOUND PROBE: #{config.inspect}"
|
|
||||||
result = email_probe_outbound( config, params[:email] )
|
|
||||||
logger.info "OUTBOUND RESULT: #{result.inspect}"
|
|
||||||
|
|
||||||
next if result[:result] != 'ok'
|
|
||||||
|
|
||||||
success = true
|
|
||||||
settings[:outbound] = config
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if !success
|
|
||||||
render json: {
|
|
||||||
result: 'failed',
|
|
||||||
}
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
render json: {
|
|
||||||
result: 'ok',
|
|
||||||
setting: settings,
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def email_outbound
|
def email_outbound
|
||||||
|
@ -609,18 +205,8 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
|
||||||
# check admin permissions
|
# check admin permissions
|
||||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||||
|
|
||||||
# validate params
|
|
||||||
if !params[:adapter]
|
|
||||||
render json: {
|
|
||||||
result: 'invalid',
|
|
||||||
}
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
# connection test
|
# connection test
|
||||||
result = email_probe_outbound( params, params[:email] )
|
render json: EmailHelper::Probe.outbound(params, params[:email])
|
||||||
|
|
||||||
render json: result
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def email_inbound
|
def email_inbound
|
||||||
|
@ -628,18 +214,8 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
|
||||||
# check admin permissions
|
# check admin permissions
|
||||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||||
|
|
||||||
# validate params
|
|
||||||
if !params[:adapter]
|
|
||||||
render json: {
|
|
||||||
result: 'invalid',
|
|
||||||
}
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
# connection test
|
# connection test
|
||||||
result = email_probe_inbound( params )
|
render json: EmailHelper::Probe.inbound(params)
|
||||||
|
|
||||||
render json: result
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def email_verify
|
def email_verify
|
||||||
|
@ -653,295 +229,80 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
|
||||||
else
|
else
|
||||||
subject = params[:subject]
|
subject = params[:subject]
|
||||||
end
|
end
|
||||||
result = email_probe_outbound( params[:outbound], params[:meta][:email], subject )
|
|
||||||
|
|
||||||
(1..5).each {
|
result = EmailHelper::Verify.email(
|
||||||
sleep 10
|
outbound: params[:outbound],
|
||||||
|
inbound: params[:inbound],
|
||||||
|
sender: params[:meta][:email],
|
||||||
|
subject: subject,
|
||||||
|
)
|
||||||
|
|
||||||
# fetch mailbox
|
# check delivery for 30 sek.
|
||||||
found = nil
|
if result[:result] != 'ok'
|
||||||
|
render json: result
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
begin
|
# remember address
|
||||||
if params[:inbound][:adapter] =~ /^imap$/i
|
address = EmailAddress.where( email: params[:meta][:email] ).first
|
||||||
found = Channel::IMAP.new.fetch( { options: params[:inbound][:options] }, 'verify', subject )
|
if !address
|
||||||
else
|
address = EmailAddress.first
|
||||||
found = Channel::POP3.new.fetch( { options: params[:inbound][:options] }, 'verify', subject )
|
end
|
||||||
end
|
if address
|
||||||
rescue => e
|
address.update_attributes(
|
||||||
render json: {
|
realname: params[:meta][:realname],
|
||||||
result: 'invalid',
|
email: params[:meta][:email],
|
||||||
message: e.to_s,
|
|
||||||
subject: subject,
|
|
||||||
}
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
next if !found
|
|
||||||
next if found != 'verify ok'
|
|
||||||
|
|
||||||
# remember address
|
|
||||||
address = EmailAddress.where( email: params[:meta][:email] ).first
|
|
||||||
if !address
|
|
||||||
address = EmailAddress.first
|
|
||||||
end
|
|
||||||
if address
|
|
||||||
address.update_attributes(
|
|
||||||
realname: params[:meta][:realname],
|
|
||||||
email: params[:meta][:email],
|
|
||||||
active: 1,
|
|
||||||
updated_by_id: 1,
|
|
||||||
created_by_id: 1,
|
|
||||||
)
|
|
||||||
else
|
|
||||||
EmailAddress.create(
|
|
||||||
realname: params[:meta][:realname],
|
|
||||||
email: params[:meta][:email],
|
|
||||||
active: 1,
|
|
||||||
updated_by_id: 1,
|
|
||||||
created_by_id: 1,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
# store mailbox
|
|
||||||
Channel.create(
|
|
||||||
area: 'Email::Inbound',
|
|
||||||
adapter: params[:inbound][:adapter],
|
|
||||||
options: params[:inbound][:options],
|
|
||||||
group_id: 1,
|
|
||||||
active: 1,
|
active: 1,
|
||||||
updated_by_id: 1,
|
updated_by_id: 1,
|
||||||
created_by_id: 1,
|
created_by_id: 1,
|
||||||
)
|
)
|
||||||
|
else
|
||||||
|
EmailAddress.create(
|
||||||
|
realname: params[:meta][:realname],
|
||||||
|
email: params[:meta][:email],
|
||||||
|
active: 1,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
# save settings
|
# store mailbox
|
||||||
if params[:outbound][:adapter] =~ /^smtp$/i
|
Channel.create(
|
||||||
smtp = Channel.where( adapter: 'SMTP', area: 'Email::Outbound' ).first
|
area: 'Email::Inbound',
|
||||||
smtp.options = params[:outbound][:options]
|
adapter: params[:inbound][:adapter],
|
||||||
smtp.active = true
|
options: params[:inbound][:options],
|
||||||
smtp.save!
|
group_id: 1,
|
||||||
sendmail = Channel.where( adapter: 'Sendmail' ).first
|
active: 1,
|
||||||
sendmail.active = false
|
updated_by_id: 1,
|
||||||
sendmail.save!
|
created_by_id: 1,
|
||||||
else
|
)
|
||||||
sendmail = Channel.where( adapter: 'Sendmail', area: 'Email::Outbound' ).first
|
|
||||||
sendmail.options = {}
|
|
||||||
sendmail.active = true
|
|
||||||
sendmail.save!
|
|
||||||
smtp = Channel.where( adapter: 'SMTP' ).first
|
|
||||||
smtp.active = false
|
|
||||||
smtp.save
|
|
||||||
end
|
|
||||||
|
|
||||||
render json: {
|
# save settings
|
||||||
result: 'ok',
|
if params[:outbound][:adapter] =~ /^smtp$/i
|
||||||
}
|
smtp = Channel.where( adapter: 'SMTP', area: 'Email::Outbound' ).first
|
||||||
return
|
smtp.options = params[:outbound][:options]
|
||||||
}
|
smtp.active = true
|
||||||
|
smtp.save!
|
||||||
|
sendmail = Channel.where( adapter: 'Sendmail' ).first
|
||||||
|
sendmail.active = false
|
||||||
|
sendmail.save!
|
||||||
|
else
|
||||||
|
sendmail = Channel.where( adapter: 'Sendmail', area: 'Email::Outbound' ).first
|
||||||
|
sendmail.options = {}
|
||||||
|
sendmail.active = true
|
||||||
|
sendmail.save!
|
||||||
|
smtp = Channel.where( adapter: 'SMTP' ).first
|
||||||
|
smtp.active = false
|
||||||
|
smtp.save
|
||||||
|
end
|
||||||
|
|
||||||
# check delivery for 30 sek.
|
|
||||||
render json: {
|
render json: {
|
||||||
result: 'invalid',
|
result: 'ok',
|
||||||
message: 'Verification Email not found in mailbox.',
|
|
||||||
subject: subject,
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def email_probe_outbound(params, email, subject = nil)
|
|
||||||
|
|
||||||
# validate params
|
|
||||||
if !params[:adapter]
|
|
||||||
result = {
|
|
||||||
result: 'invalid',
|
|
||||||
message: 'Invalid, need adapter!',
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
if subject
|
|
||||||
mail = {
|
|
||||||
:from => email,
|
|
||||||
:to => email,
|
|
||||||
:subject => "Zammad Getting started Test Email #{subject}",
|
|
||||||
:body => "This is a Test Email of Zammad to check if sending and receiving is working correctly.\n\nYou can ignore or delete this email.",
|
|
||||||
'x-zammad-ignore' => 'true',
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mail = {
|
|
||||||
from: email,
|
|
||||||
to: 'emailtrytest@znuny.com',
|
|
||||||
subject: 'test',
|
|
||||||
body: 'test',
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
# test connection
|
|
||||||
translation_map = {
|
|
||||||
'authentication failed' => 'Authentication failed!',
|
|
||||||
'Incorrect username' => 'Authentication failed!',
|
|
||||||
'getaddrinfo: nodename nor servname provided, or not known' => 'Hostname not found!',
|
|
||||||
'No route to host' => 'No route to host!',
|
|
||||||
'Connection refused' => 'Connection refused!',
|
|
||||||
}
|
|
||||||
if params[:adapter] =~ /^smtp$/i
|
|
||||||
|
|
||||||
# in case, fill missing params
|
|
||||||
if !params[:options].key?(:port)
|
|
||||||
params[:options][:port] = 25
|
|
||||||
end
|
|
||||||
if !params[:options].key?(:ssl)
|
|
||||||
params[:options][:ssl] = true
|
|
||||||
end
|
|
||||||
|
|
||||||
begin
|
|
||||||
Channel::SMTP.new.send(
|
|
||||||
mail,
|
|
||||||
{
|
|
||||||
options: params[:options]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
rescue => e
|
|
||||||
|
|
||||||
# check if sending email was ok, but mailserver rejected
|
|
||||||
if !subject
|
|
||||||
white_map = {
|
|
||||||
'Recipient address rejected' => true,
|
|
||||||
}
|
|
||||||
white_map.each {|key, _message|
|
|
||||||
|
|
||||||
next if e.message !~ /#{Regexp.escape(key)}/i
|
|
||||||
|
|
||||||
result = {
|
|
||||||
result: 'ok',
|
|
||||||
settings: params,
|
|
||||||
notice: e.message,
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
end
|
|
||||||
message_human = ''
|
|
||||||
translation_map.each {|key, message|
|
|
||||||
if e.message =~ /#{Regexp.escape(key)}/i
|
|
||||||
message_human = message
|
|
||||||
end
|
|
||||||
}
|
|
||||||
result = {
|
|
||||||
result: 'invalid',
|
|
||||||
settings: params,
|
|
||||||
message: e.message,
|
|
||||||
message_human: message_human,
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
result = {
|
|
||||||
result: 'ok',
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
begin
|
|
||||||
Channel::Sendmail.new.send(
|
|
||||||
mail,
|
|
||||||
nil
|
|
||||||
)
|
|
||||||
rescue => e
|
|
||||||
message_human = ''
|
|
||||||
translation_map.each {|key, message|
|
|
||||||
if e.message =~ /#{Regexp.escape(key)}/i
|
|
||||||
message_human = message
|
|
||||||
end
|
|
||||||
}
|
|
||||||
result = {
|
|
||||||
result: 'invalid',
|
|
||||||
settings: params,
|
|
||||||
message: e.message,
|
|
||||||
message_human: message_human,
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
result = {
|
|
||||||
result: 'ok',
|
|
||||||
}
|
|
||||||
result
|
|
||||||
end
|
|
||||||
|
|
||||||
def email_probe_inbound(params)
|
|
||||||
|
|
||||||
# validate params
|
|
||||||
if !params[:adapter]
|
|
||||||
fail 'need :adapter param'
|
|
||||||
end
|
|
||||||
|
|
||||||
# connection test
|
|
||||||
translation_map = {
|
|
||||||
'authentication failed' => 'Authentication failed!',
|
|
||||||
'Incorrect username' => 'Authentication failed!',
|
|
||||||
'getaddrinfo: nodename nor servname provided, or not known' => 'Hostname not found!',
|
|
||||||
'No route to host' => 'No route to host!',
|
|
||||||
'Connection refused' => 'Connection refused!',
|
|
||||||
}
|
|
||||||
if params[:adapter] =~ /^imap$/i
|
|
||||||
|
|
||||||
begin
|
|
||||||
Channel::IMAP.new.fetch( { options: params[:options] }, 'check' )
|
|
||||||
rescue => e
|
|
||||||
message_human = ''
|
|
||||||
translation_map.each {|key, message|
|
|
||||||
if e.message =~ /#{Regexp.escape(key)}/i
|
|
||||||
message_human = message
|
|
||||||
end
|
|
||||||
}
|
|
||||||
result = {
|
|
||||||
result: 'invalid',
|
|
||||||
settings: params,
|
|
||||||
message: e.message,
|
|
||||||
message_human: message_human,
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
result = {
|
|
||||||
result: 'ok',
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
begin
|
|
||||||
Channel::POP3.new.fetch( { options: params[:options] }, 'check' )
|
|
||||||
rescue => e
|
|
||||||
message_human = ''
|
|
||||||
translation_map.each {|key, message|
|
|
||||||
if e.message =~ /#{Regexp.escape(key)}/i
|
|
||||||
message_human = message
|
|
||||||
end
|
|
||||||
}
|
|
||||||
result = {
|
|
||||||
result: 'invalid',
|
|
||||||
settings: params,
|
|
||||||
message: e.message,
|
|
||||||
message_human: message_human,
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
result = {
|
|
||||||
result: 'ok',
|
|
||||||
}
|
|
||||||
result
|
|
||||||
end
|
|
||||||
|
|
||||||
def mxers(domain)
|
|
||||||
begin
|
|
||||||
mxs = Resolv::DNS.open do |dns|
|
|
||||||
ress = dns.getresources(domain, Resolv::DNS::Resource::IN::MX)
|
|
||||||
ress.map { |r| [r.exchange.to_s, IPSocket.getaddress(r.exchange.to_s), r.preference] }
|
|
||||||
end
|
|
||||||
rescue => e
|
|
||||||
logger.error e.message
|
|
||||||
logger.error e.backtrace.inspect
|
|
||||||
end
|
|
||||||
mxs
|
|
||||||
end
|
|
||||||
|
|
||||||
def auto_wizard_enabled_response
|
def auto_wizard_enabled_response
|
||||||
return false if !AutoWizard.enabled?
|
return false if !AutoWizard.enabled?
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,13 @@ class Channel < ApplicationModel
|
||||||
# 'warning: toplevel constant Twitter referenced by Channel::Twitter' error e.g.
|
# 'warning: toplevel constant Twitter referenced by Channel::Twitter' error e.g.
|
||||||
# so we have to convert the channel name to the filename via Rails String.underscore
|
# so we have to convert the channel name to the filename via Rails String.underscore
|
||||||
# http://stem.ps/rails/2015/01/25/ruby-gotcha-toplevel-constant-referenced-by.html
|
# http://stem.ps/rails/2015/01/25/ruby-gotcha-toplevel-constant-referenced-by.html
|
||||||
require "channel/#{channel[:adapter].underscore}"
|
require "channel/#{channel[:adapter].to_filename}"
|
||||||
|
|
||||||
channel_object = Object.const_get("Channel::#{channel[:adapter]}")
|
channel_object = Object.const_get("Channel::#{channel[:adapter].to_classname}")
|
||||||
channel_instance = channel_object.new
|
channel_instance = channel_object.new
|
||||||
channel_instance.fetch(channel)
|
channel_instance.fetch(channel)
|
||||||
rescue => e
|
rescue => e
|
||||||
logger.error "Can't use Channel::#{channel[:adapter]}"
|
logger.error "Can't use Channel::#{channel[:adapter].to_classname}"
|
||||||
logger.error e.inspect
|
logger.error e.inspect
|
||||||
logger.error e.backtrace
|
logger.error e.backtrace
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
require 'net/imap'
|
require 'net/imap'
|
||||||
|
|
||||||
class Channel::IMAP < Channel::EmailParser
|
class Channel::Imap < Channel::EmailParser
|
||||||
|
|
||||||
def fetch (channel, check_type = '', verify_string = '')
|
def fetch (channel, check_type = '', verify_string = '')
|
||||||
ssl = true
|
ssl = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
require 'net/pop'
|
require 'net/pop'
|
||||||
|
|
||||||
class Channel::POP3 < Channel::EmailParser
|
class Channel::Pop3 < Channel::EmailParser
|
||||||
|
|
||||||
def fetch (channel, check_type = '', verify_string = '')
|
def fetch (channel, check_type = '', verify_string = '')
|
||||||
ssl = true
|
ssl = true
|
||||||
|
|
614
lib/email_helper.rb
Normal file
614
lib/email_helper.rb
Normal file
|
@ -0,0 +1,614 @@
|
||||||
|
module EmailHelper
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get mail parts
|
||||||
|
|
||||||
|
user, domain = EmailHelper.parse_email('somebody@example.com')
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
[user, domain]
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.parse_email(email)
|
||||||
|
user = nil
|
||||||
|
domain = nil
|
||||||
|
if email =~ /^(.+?)@(.+?)$/
|
||||||
|
user = $1
|
||||||
|
domain = $2
|
||||||
|
end
|
||||||
|
[user, domain]
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get list of providers with inbound and outbound settings
|
||||||
|
|
||||||
|
map = EmailHelper.provider(email, password)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
{
|
||||||
|
google: {
|
||||||
|
domain: 'gmail.com|googlemail.com|gmail.de',
|
||||||
|
inbound: {
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: 'imap.gmail.com',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outbound: {
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: 'smtp.gmail.com',
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.provider(email, password)
|
||||||
|
# check domain based attributes
|
||||||
|
provider_map = {
|
||||||
|
google: {
|
||||||
|
domain: 'gmail.com|googlemail.com|gmail.de',
|
||||||
|
inbound: {
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: 'imap.gmail.com',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outbound: {
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: 'smtp.gmail.com',
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
microsoft: {
|
||||||
|
domain: 'outlook.com|hotmail.com',
|
||||||
|
inbound: {
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: 'imap-mail.outlook.com',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outbound: {
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: 'smtp-mail.outlook.com',
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
provider_map
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get possible inbound settings based on mx
|
||||||
|
|
||||||
|
map = EmailHelper.provider_inbound_mx(user, email, password, mx_domains)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: mx_domains[0],
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: mx_domains[0],
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.provider_inbound_mx(user, email, password, mx_domains)
|
||||||
|
inbound_mxs = []
|
||||||
|
mx_domains.each {|domain|
|
||||||
|
inbound_mx = [
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: domain,
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: domain,
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
puts "ll #{inbound_mx.inspect}"
|
||||||
|
inbound_mxs = inbound_mxs.concat(inbound_mx)
|
||||||
|
}
|
||||||
|
inbound_mxs
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get possible inbound settings based on mx
|
||||||
|
|
||||||
|
map = EmailHelper.provider_inbound_mx(user, email, password, mx_domains)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: mx_domains[0],
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: mx_domains[0],
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.provider_inbound_mx(user, email, password, mx_domains)
|
||||||
|
inbounds = []
|
||||||
|
mx_domains.each {|domain|
|
||||||
|
inbound = [
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: domain,
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: domain,
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
inbounds = inbounds.concat(inbound)
|
||||||
|
}
|
||||||
|
inbounds
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get possible inbound settings based on guess
|
||||||
|
|
||||||
|
map = EmailHelper.provider_inbound_guess(user, email, password, domain)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: "mail.#{domain}",
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: "mail.#{domain}",
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.provider_inbound_guess(user, email, password, domain)
|
||||||
|
inbound_mx = [
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: "mail.#{domain}",
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: "mail.#{domain}",
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: "imap.#{domain}",
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: "imap.#{domain}",
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'pop3',
|
||||||
|
options: {
|
||||||
|
host: "mail.#{domain}",
|
||||||
|
port: 995,
|
||||||
|
ssl: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'pop3',
|
||||||
|
options: {
|
||||||
|
host: "mail.#{domain}",
|
||||||
|
port: 995,
|
||||||
|
ssl: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'pop3',
|
||||||
|
options: {
|
||||||
|
host: "pop.#{domain}",
|
||||||
|
port: 995,
|
||||||
|
ssl: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'pop3',
|
||||||
|
options: {
|
||||||
|
host: "pop.#{domain}",
|
||||||
|
port: 995,
|
||||||
|
ssl: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'pop3',
|
||||||
|
options: {
|
||||||
|
host: "pop3.#{domain}",
|
||||||
|
port: 995,
|
||||||
|
ssl: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'pop3',
|
||||||
|
options: {
|
||||||
|
host: "pop3.#{domain}",
|
||||||
|
port: 995,
|
||||||
|
ssl: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
inbound_mx
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get possible outbound settings based on mx
|
||||||
|
|
||||||
|
map = EmailHelper.provider_outbound_mx(user, email, password, mx_domains)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: domain,
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: domain,
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.provider_outbound_mx(user, email, password, mx_domains)
|
||||||
|
outbound_mxs = []
|
||||||
|
mx_domains.each {|domain|
|
||||||
|
outbound_mx = [
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: domain,
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: domain,
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: domain,
|
||||||
|
port: 465,
|
||||||
|
start_tls: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: domain,
|
||||||
|
port: 465,
|
||||||
|
start_tls: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
outbound_mxs = outbound_mxs.concat(outbound_mx)
|
||||||
|
}
|
||||||
|
outbound_mxs
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get possible outbound settings based on guess
|
||||||
|
|
||||||
|
map = EmailHelper.provider_outbound_guess(user, email, password, domain)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: "mail.#{domain}",
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: "mail.#{domain}",
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.provider_outbound_guess(user, email, password, domain)
|
||||||
|
outbound_mx = [
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: "mail.#{domain}",
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: "mail.#{domain}",
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: "mail.#{domain}",
|
||||||
|
port: 465,
|
||||||
|
start_tls: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: "mail.#{domain}",
|
||||||
|
port: 465,
|
||||||
|
start_tls: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: "smtp.#{domain}",
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: "smtp.#{domain}",
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: "smtp.#{domain}",
|
||||||
|
port: 465,
|
||||||
|
start_tls: true,
|
||||||
|
user: user,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: "smtp.#{domain}",
|
||||||
|
port: 465,
|
||||||
|
start_tls: true,
|
||||||
|
user: email,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
outbound_mx
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get dns mx records of domain
|
||||||
|
|
||||||
|
mx_records = EmailHelper.mx_records('example.com')
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
['mx1.example.com', 'mx2.example.com']
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.mx_records(domain)
|
||||||
|
mail_exchangers = mxers(domain)
|
||||||
|
if mail_exchangers && mail_exchangers[0]
|
||||||
|
Rails.logger.info "MX for #{domain}: #{mail_exchangers} - #{mail_exchangers[0][0]}"
|
||||||
|
end
|
||||||
|
mx_records = []
|
||||||
|
if mail_exchangers && mail_exchangers[0] && mail_exchangers[0][0]
|
||||||
|
mx_records.push mail_exchangers[0][0]
|
||||||
|
end
|
||||||
|
mx_records
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.mxers(domain)
|
||||||
|
begin
|
||||||
|
mxs = Resolv::DNS.open do |dns|
|
||||||
|
ress = dns.getresources(domain, Resolv::DNS::Resource::IN::MX)
|
||||||
|
ress.map { |r|
|
||||||
|
[r.exchange.to_s, IPSocket.getaddress(r.exchange.to_s), r.preference]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
rescue => e
|
||||||
|
Rails.logger.error e.message
|
||||||
|
Rails.logger.error e.backtrace.inspect
|
||||||
|
end
|
||||||
|
mxs
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
376
lib/email_helper/probe.rb
Normal file
376
lib/email_helper/probe.rb
Normal file
|
@ -0,0 +1,376 @@
|
||||||
|
module EmailHelper
|
||||||
|
class Probe
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get result of probe
|
||||||
|
|
||||||
|
result = EmailHelper::Probe.full(
|
||||||
|
email: 'znuny@example.com',
|
||||||
|
password: 'somepassword',
|
||||||
|
)
|
||||||
|
|
||||||
|
returns on success
|
||||||
|
|
||||||
|
{
|
||||||
|
result: 'ok',
|
||||||
|
inbound: {
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: 'imap.gmail.com',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outbound: {
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: 'smtp.gmail.com',
|
||||||
|
port: 25,
|
||||||
|
ssl: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
returns on fail
|
||||||
|
|
||||||
|
result = {
|
||||||
|
result: 'failed',
|
||||||
|
}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.full(params)
|
||||||
|
|
||||||
|
user, domain = EmailHelper.parse_email(params[:email])
|
||||||
|
|
||||||
|
if !user || !domain
|
||||||
|
result = {
|
||||||
|
result: 'invalid',
|
||||||
|
messages: {
|
||||||
|
email: 'Invalid email.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
# probe provider based settings
|
||||||
|
provider_map = EmailHelper.provider(params[:email], params[:password])
|
||||||
|
domains = [domain]
|
||||||
|
|
||||||
|
# get mx records, try to find provider based on mx records
|
||||||
|
mx_records = EmailHelper.mx_records(domain)
|
||||||
|
domains = domains.concat(mx_records)
|
||||||
|
provider_map.each {|_provider, settings|
|
||||||
|
domains.each {|domain_to_check|
|
||||||
|
|
||||||
|
next if domain_to_check !~ /#{settings[:domain]}/i
|
||||||
|
|
||||||
|
# probe inbound
|
||||||
|
result = EmailHelper::Probe.inbound(settings[:inbound])
|
||||||
|
next if result[:result] != 'ok'
|
||||||
|
|
||||||
|
# probe outbound
|
||||||
|
result = EmailHelper::Probe.outbound(settings[:outbound], params[:email])
|
||||||
|
next if result[:result] != 'ok'
|
||||||
|
|
||||||
|
result = {
|
||||||
|
result: 'ok',
|
||||||
|
setting: settings,
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# probe guess settings
|
||||||
|
|
||||||
|
# probe inbound
|
||||||
|
inbound_mx = EmailHelper.provider_inbound_mx(user, params[:email], params[:password], mx_records)
|
||||||
|
inbound_guess = EmailHelper.provider_inbound_guess(user, params[:email], params[:password], domain)
|
||||||
|
inbound_map = inbound_mx + inbound_guess
|
||||||
|
settings = {}
|
||||||
|
success = false
|
||||||
|
inbound_map.each {|config|
|
||||||
|
Rails.logger.info "INBOUND PROBE: #{config.inspect}"
|
||||||
|
result = EmailHelper::Probe.inbound( config )
|
||||||
|
Rails.logger.info "INBOUND RESULT: #{result.inspect}"
|
||||||
|
|
||||||
|
next if result[:result] != 'ok'
|
||||||
|
|
||||||
|
success = true
|
||||||
|
settings[:inbound] = config
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if !success
|
||||||
|
result = {
|
||||||
|
result: 'failed',
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
# probe outbound
|
||||||
|
outbound_mx = EmailHelper.provider_outbound_mx(user, params[:email], params[:password], mx_records)
|
||||||
|
outbound_guess = EmailHelper.provider_outbound_guess(user, params[:email], params[:password], domain)
|
||||||
|
outbound_map = outbound_mx + outbound_guess
|
||||||
|
|
||||||
|
success = false
|
||||||
|
outbound_map.each {|config|
|
||||||
|
Rails.logger.info "OUTBOUND PROBE: #{config.inspect}"
|
||||||
|
result = EmailHelper::Probe.outbound( config, params[:email] )
|
||||||
|
Rails.logger.info "OUTBOUND RESULT: #{result.inspect}"
|
||||||
|
|
||||||
|
next if result[:result] != 'ok'
|
||||||
|
|
||||||
|
success = true
|
||||||
|
settings[:outbound] = config
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if !success
|
||||||
|
result = {
|
||||||
|
result: 'failed',
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
{
|
||||||
|
result: 'ok',
|
||||||
|
setting: settings,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get result of inbound probe
|
||||||
|
|
||||||
|
result = EmailHelper::Probe.inbound(
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: 'imap.gmail.com',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
returns on success
|
||||||
|
|
||||||
|
{
|
||||||
|
result: 'ok'
|
||||||
|
}
|
||||||
|
|
||||||
|
returns on fail
|
||||||
|
|
||||||
|
result = {
|
||||||
|
result: 'invalid',
|
||||||
|
settings: {
|
||||||
|
host: 'imap.gmail.com',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
},
|
||||||
|
message: 'error message from used lib',
|
||||||
|
message_human: 'translated error message, readable for humans',
|
||||||
|
}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.inbound(params)
|
||||||
|
|
||||||
|
# validate params
|
||||||
|
if !params[:adapter]
|
||||||
|
result = {
|
||||||
|
result: 'invalid',
|
||||||
|
message: 'Invalid, need adapter!',
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
# connection test
|
||||||
|
begin
|
||||||
|
if params[:adapter] =~ /^imap$/i
|
||||||
|
Channel::Imap.new.fetch( { options: params[:options] }, 'check' )
|
||||||
|
elsif params[:adapter] =~ /^pop3$/i
|
||||||
|
Channel::Pop3.new.fetch( { options: params[:options] }, 'check' )
|
||||||
|
else
|
||||||
|
fail "Invalid adapter '#{params[:adapter]}'"
|
||||||
|
end
|
||||||
|
rescue => e
|
||||||
|
message_human = ''
|
||||||
|
translations.each {|key, message|
|
||||||
|
if e.message =~ /#{Regexp.escape(key)}/i
|
||||||
|
message_human = message
|
||||||
|
end
|
||||||
|
}
|
||||||
|
result = {
|
||||||
|
result: 'invalid',
|
||||||
|
settings: params,
|
||||||
|
message: e.message,
|
||||||
|
message_human: message_human,
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
result = {
|
||||||
|
result: 'ok',
|
||||||
|
}
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get result of outbound probe
|
||||||
|
|
||||||
|
result = EmailHelper::Probe.outbound(
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: 'smtp.gmail.com',
|
||||||
|
port: 25,
|
||||||
|
ssl: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'sender@example.com',
|
||||||
|
)
|
||||||
|
|
||||||
|
returns on success
|
||||||
|
|
||||||
|
{
|
||||||
|
result: 'ok'
|
||||||
|
}
|
||||||
|
|
||||||
|
returns on fail
|
||||||
|
|
||||||
|
result = {
|
||||||
|
result: 'invalid',
|
||||||
|
settings: {
|
||||||
|
host: 'stmp.gmail.com',
|
||||||
|
port: 25,
|
||||||
|
ssl: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
},
|
||||||
|
message: 'error message from used lib',
|
||||||
|
message_human: 'translated error message, readable for humans',
|
||||||
|
}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.outbound(params, email, subject = nil)
|
||||||
|
|
||||||
|
# validate params
|
||||||
|
if !params[:adapter]
|
||||||
|
result = {
|
||||||
|
result: 'invalid',
|
||||||
|
message: 'Invalid, need adapter!',
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
if subject
|
||||||
|
mail = {
|
||||||
|
:from => email,
|
||||||
|
:to => email,
|
||||||
|
:subject => "Zammad Getting started Test Email #{subject}",
|
||||||
|
:body => "This is a Test Email of Zammad to check if sending and receiving is working correctly.\n\nYou can ignore or delete this email.",
|
||||||
|
'x-zammad-ignore' => 'true',
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mail = {
|
||||||
|
from: email,
|
||||||
|
to: 'emailtrytest@znuny.com',
|
||||||
|
subject: 'This is a Test Email',
|
||||||
|
body: "This is a Test Email of Zammad to verify if Zammad can send emails to an external address.\n\nIf you see this email, you can ignore and delete it.",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# test connection
|
||||||
|
begin
|
||||||
|
|
||||||
|
if params[:adapter] =~ /^smtp$/i
|
||||||
|
|
||||||
|
# in case, fill missing params
|
||||||
|
if !params[:options].key?(:port)
|
||||||
|
params[:options][:port] = 25
|
||||||
|
end
|
||||||
|
if !params[:options].key?(:ssl)
|
||||||
|
params[:options][:ssl] = true
|
||||||
|
end
|
||||||
|
Channel::SMTP.new.send(
|
||||||
|
mail,
|
||||||
|
{
|
||||||
|
options: params[:options]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
elsif params[:adapter] =~ /^sendmail$/i
|
||||||
|
Channel::Sendmail.new.send(
|
||||||
|
mail,
|
||||||
|
nil
|
||||||
|
)
|
||||||
|
else
|
||||||
|
fail "Invalid adapter '#{params[:adapter]}'"
|
||||||
|
end
|
||||||
|
rescue => e
|
||||||
|
|
||||||
|
# check if sending email was ok, but mailserver rejected
|
||||||
|
if !subject
|
||||||
|
white_map = {
|
||||||
|
'Recipient address rejected' => true,
|
||||||
|
}
|
||||||
|
white_map.each {|key, _message|
|
||||||
|
|
||||||
|
next if e.message !~ /#{Regexp.escape(key)}/i
|
||||||
|
|
||||||
|
result = {
|
||||||
|
result: 'ok',
|
||||||
|
settings: params,
|
||||||
|
notice: e.message,
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
end
|
||||||
|
message_human = ''
|
||||||
|
translations.each {|key, message|
|
||||||
|
if e.message =~ /#{Regexp.escape(key)}/i
|
||||||
|
message_human = message
|
||||||
|
end
|
||||||
|
}
|
||||||
|
result = {
|
||||||
|
result: 'invalid',
|
||||||
|
settings: params,
|
||||||
|
message: e.message,
|
||||||
|
message_human: message_human,
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
result = {
|
||||||
|
result: 'ok',
|
||||||
|
}
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.translations
|
||||||
|
{
|
||||||
|
'authentication failed' => 'Authentication failed!',
|
||||||
|
'Username and Password not accepted' => 'Authentication failed!',
|
||||||
|
'Incorrect username' => 'Authentication failed, username incorrect!',
|
||||||
|
'Lookup failed' => 'Authentication failed, username incorrect!',
|
||||||
|
'Invalid credentials' => 'Authentication failed, invalid credentials!',
|
||||||
|
'getaddrinfo: nodename nor servname provided, or not known' => 'Hostname not found!',
|
||||||
|
'No route to host' => 'No route to host!',
|
||||||
|
'execution expired' => 'Host not reachable!',
|
||||||
|
'Connection refused' => 'Connection refused!',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
106
lib/email_helper/verify.rb
Normal file
106
lib/email_helper/verify.rb
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
module EmailHelper
|
||||||
|
class Verify
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get result of inbound probe
|
||||||
|
|
||||||
|
result = EmailHelper::Verify.email(
|
||||||
|
inbound: {
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: 'imap.gmail.com',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outbound: {
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: 'smtp.gmail.com',
|
||||||
|
port: 25,
|
||||||
|
ssl: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sender: 'sender@example.com',
|
||||||
|
)
|
||||||
|
|
||||||
|
returns on success
|
||||||
|
|
||||||
|
{
|
||||||
|
result: 'ok'
|
||||||
|
}
|
||||||
|
|
||||||
|
returns on fail
|
||||||
|
|
||||||
|
{
|
||||||
|
result: 'invalid',
|
||||||
|
message: 'Verification Email not found in mailbox.',
|
||||||
|
subject: subject,
|
||||||
|
}
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
{
|
||||||
|
result: 'invalid',
|
||||||
|
message: 'Authentication failed!.',
|
||||||
|
subject: subject,
|
||||||
|
}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.email(params)
|
||||||
|
|
||||||
|
# send verify email
|
||||||
|
if !params[:subject]
|
||||||
|
subject = '#' + rand(99_999_999_999).to_s
|
||||||
|
else
|
||||||
|
subject = params[:subject]
|
||||||
|
end
|
||||||
|
result = EmailHelper::Probe.outbound( params[:outbound], params[:sender], subject )
|
||||||
|
|
||||||
|
# looking for verify email
|
||||||
|
(1..5).each {
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# fetch mailbox
|
||||||
|
found = nil
|
||||||
|
|
||||||
|
begin
|
||||||
|
if params[:inbound][:adapter] =~ /^imap$/i
|
||||||
|
found = Channel::Imap.new.fetch( { options: params[:inbound][:options] }, 'verify', subject )
|
||||||
|
else
|
||||||
|
found = Channel::Pop3.new.fetch( { options: params[:inbound][:options] }, 'verify', subject )
|
||||||
|
end
|
||||||
|
rescue => e
|
||||||
|
render json: {
|
||||||
|
result: 'invalid',
|
||||||
|
message: e.to_s,
|
||||||
|
subject: subject,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
next if !found
|
||||||
|
next if found != 'verify ok'
|
||||||
|
|
||||||
|
return {
|
||||||
|
result: 'ok',
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
result: 'invalid',
|
||||||
|
message: 'Verification Email not found in mailbox.',
|
||||||
|
subject: subject,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
445
test/unit/email_helper_test.rb
Normal file
445
test/unit/email_helper_test.rb
Normal file
|
@ -0,0 +1,445 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class EmailHelperTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
|
test 'a mx_records' do
|
||||||
|
|
||||||
|
domain = 'znuny.com'
|
||||||
|
mx_domains = EmailHelper.mx_records(domain)
|
||||||
|
assert_equal('arber.znuny.com', mx_domains[0])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'a email parser test' do
|
||||||
|
|
||||||
|
user, domain = EmailHelper.parse_email('somebody@example.com')
|
||||||
|
assert_equal('somebody', user)
|
||||||
|
assert_equal('example.com', domain)
|
||||||
|
|
||||||
|
user, domain = EmailHelper.parse_email('somebody+test@example.com')
|
||||||
|
assert_equal('somebody+test', user)
|
||||||
|
assert_equal('example.com', domain)
|
||||||
|
|
||||||
|
user, domain = EmailHelper.parse_email('somebody+testexample.com')
|
||||||
|
assert_not(user)
|
||||||
|
assert_not(domain)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'provider test' do
|
||||||
|
email = 'linus@kernel.org'
|
||||||
|
password = 'some_pw'
|
||||||
|
map = EmailHelper.provider(email, password)
|
||||||
|
|
||||||
|
assert_equal('imap', map[:google][:inbound][:adapter])
|
||||||
|
assert_equal('imap.gmail.com', map[:google][:inbound][:options][:host])
|
||||||
|
assert_equal(993, map[:google][:inbound][:options][:port])
|
||||||
|
assert_equal(email, map[:google][:inbound][:options][:user])
|
||||||
|
assert_equal(password, map[:google][:inbound][:options][:password])
|
||||||
|
|
||||||
|
assert_equal('smtp', map[:google][:outbound][:adapter])
|
||||||
|
assert_equal('smtp.gmail.com', map[:google][:outbound][:options][:host])
|
||||||
|
assert_equal(25, map[:google][:outbound][:options][:port])
|
||||||
|
assert_equal(true, map[:google][:outbound][:options][:start_tls])
|
||||||
|
assert_equal(email, map[:google][:outbound][:options][:user])
|
||||||
|
assert_equal(password, map[:google][:outbound][:options][:password])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'provider_inbound_mx' do
|
||||||
|
|
||||||
|
email = 'linus@znuny.com'
|
||||||
|
password = 'some_pw'
|
||||||
|
user, domain = EmailHelper.parse_email(email)
|
||||||
|
mx_domains = EmailHelper.mx_records(domain)
|
||||||
|
map = EmailHelper.provider_inbound_mx(user, email, password, mx_domains)
|
||||||
|
|
||||||
|
assert_equal('imap', map[0][:adapter])
|
||||||
|
assert_equal('arber.znuny.com', map[0][:options][:host])
|
||||||
|
assert_equal(993, map[0][:options][:port])
|
||||||
|
assert_equal(user, map[0][:options][:user])
|
||||||
|
assert_equal(password, map[0][:options][:password])
|
||||||
|
|
||||||
|
assert_equal('imap', map[1][:adapter])
|
||||||
|
assert_equal('arber.znuny.com', map[1][:options][:host])
|
||||||
|
assert_equal(993, map[1][:options][:port])
|
||||||
|
assert_equal(email, map[1][:options][:user])
|
||||||
|
assert_equal(password, map[1][:options][:password])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'provider_inbound_guess' do
|
||||||
|
|
||||||
|
email = 'linus@znuny.com'
|
||||||
|
password = 'some_pw'
|
||||||
|
user, domain = EmailHelper.parse_email(email)
|
||||||
|
map = EmailHelper.provider_inbound_guess(user, email, password, domain)
|
||||||
|
|
||||||
|
assert_equal('imap', map[0][:adapter])
|
||||||
|
assert_equal('mail.znuny.com', map[0][:options][:host])
|
||||||
|
assert_equal(993, map[0][:options][:port])
|
||||||
|
assert_equal(user, map[0][:options][:user])
|
||||||
|
assert_equal(password, map[0][:options][:password])
|
||||||
|
|
||||||
|
assert_equal('imap', map[1][:adapter])
|
||||||
|
assert_equal('mail.znuny.com', map[1][:options][:host])
|
||||||
|
assert_equal(993, map[1][:options][:port])
|
||||||
|
assert_equal(email, map[1][:options][:user])
|
||||||
|
assert_equal(password, map[1][:options][:password])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'provider_outbound_mx' do
|
||||||
|
|
||||||
|
email = 'linus@znuny.com'
|
||||||
|
password = 'some_pw'
|
||||||
|
user, domain = EmailHelper.parse_email(email)
|
||||||
|
mx_domains = EmailHelper.mx_records(domain)
|
||||||
|
map = EmailHelper.provider_outbound_mx(user, email, password, mx_domains)
|
||||||
|
|
||||||
|
assert_equal('smtp', map[0][:adapter])
|
||||||
|
assert_equal('arber.znuny.com', map[0][:options][:host])
|
||||||
|
assert_equal(25, map[0][:options][:port])
|
||||||
|
assert_equal(true, map[0][:options][:start_tls])
|
||||||
|
assert_equal(user, map[0][:options][:user])
|
||||||
|
assert_equal(password, map[0][:options][:password])
|
||||||
|
|
||||||
|
assert_equal('smtp', map[1][:adapter])
|
||||||
|
assert_equal('arber.znuny.com', map[1][:options][:host])
|
||||||
|
assert_equal(25, map[1][:options][:port])
|
||||||
|
assert_equal(true, map[1][:options][:start_tls])
|
||||||
|
assert_equal(email, map[1][:options][:user])
|
||||||
|
assert_equal(password, map[1][:options][:password])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'provider_outbound_guess' do
|
||||||
|
|
||||||
|
email = 'linus@znuny.com'
|
||||||
|
password = 'some_pw'
|
||||||
|
user, domain = EmailHelper.parse_email(email)
|
||||||
|
map = EmailHelper.provider_outbound_guess(user, email, password, domain)
|
||||||
|
|
||||||
|
assert_equal('smtp', map[0][:adapter])
|
||||||
|
assert_equal('mail.znuny.com', map[0][:options][:host])
|
||||||
|
assert_equal(25, map[0][:options][:port])
|
||||||
|
assert_equal(true, map[0][:options][:start_tls])
|
||||||
|
assert_equal(user, map[0][:options][:user])
|
||||||
|
assert_equal(password, map[0][:options][:password])
|
||||||
|
|
||||||
|
assert_equal('smtp', map[1][:adapter])
|
||||||
|
assert_equal('mail.znuny.com', map[1][:options][:host])
|
||||||
|
assert_equal(25, map[1][:options][:port])
|
||||||
|
assert_equal(true, map[1][:options][:start_tls])
|
||||||
|
assert_equal(email, map[1][:options][:user])
|
||||||
|
assert_equal(password, map[1][:options][:password])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'z probe_inbound' do
|
||||||
|
|
||||||
|
# network issues
|
||||||
|
result = EmailHelper::Probe.inbound(
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: 'not_existsing_host',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_equal('invalid', result[:result])
|
||||||
|
assert_equal('Hostname not found!', result[:message_human])
|
||||||
|
assert_equal('not_existsing_host', result[:settings][:options][:host])
|
||||||
|
|
||||||
|
result = EmailHelper::Probe.inbound(
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: 'www.zammad.com',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert_equal('invalid', result[:result])
|
||||||
|
assert_equal('Connection refused!', result[:message_human])
|
||||||
|
assert_equal('www.zammad.com', result[:settings][:options][:host])
|
||||||
|
|
||||||
|
result = EmailHelper::Probe.inbound(
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: '172.42.42.42',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert_equal('invalid', result[:result])
|
||||||
|
assert_equal('Host not reachable!', result[:message_human])
|
||||||
|
assert_equal('172.42.42.42', result[:settings][:options][:host])
|
||||||
|
|
||||||
|
# gmail
|
||||||
|
result = EmailHelper::Probe.inbound(
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: 'imap.gmail.com',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert_equal('invalid', result[:result])
|
||||||
|
assert_equal('Authentication failed, username incorrect!', result[:message_human])
|
||||||
|
assert_equal('imap.gmail.com', result[:settings][:options][:host])
|
||||||
|
|
||||||
|
result = EmailHelper::Probe.inbound(
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: 'imap.gmail.com',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: 'frank.tailor05@googlemail.com',
|
||||||
|
password: 'password',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert_equal('invalid', result[:result])
|
||||||
|
assert_equal('Authentication failed, invalid credentials!', result[:message_human])
|
||||||
|
assert_equal('imap.gmail.com', result[:settings][:options][:host])
|
||||||
|
|
||||||
|
# dovecot
|
||||||
|
result = EmailHelper::Probe.inbound(
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: 'arber.znuny.com',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert_equal('invalid', result[:result])
|
||||||
|
assert_equal('Authentication failed!', result[:message_human])
|
||||||
|
assert_equal('arber.znuny.com', result[:settings][:options][:host])
|
||||||
|
|
||||||
|
# realtest - test I
|
||||||
|
if !ENV['EMAILHELPER_MAILBOX_1']
|
||||||
|
raise "Need EMAILHELPER_MAILBOX_1 as ENV variable like export EMAILHELPER_MAILBOX_1='unittestemailhelper01@znuny.com:somepass'"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
mailbox_user = ENV['EMAILHELPER_MAILBOX_1'].split(':')[0]
|
||||||
|
mailbox_password = ENV['EMAILHELPER_MAILBOX_1'].split(':')[1]
|
||||||
|
user, domain = EmailHelper.parse_email(mailbox_user)
|
||||||
|
result = EmailHelper::Probe.inbound(
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: 'arber.znuny.com',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: user,
|
||||||
|
password: mailbox_password,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert_equal('ok', result[:result])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'z probe_outbound' do
|
||||||
|
|
||||||
|
# network issues
|
||||||
|
result = EmailHelper::Probe.outbound(
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: 'not_existsing_host',
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'some@example.com',
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_equal('invalid', result[:result])
|
||||||
|
assert_equal('Hostname not found!', result[:message_human])
|
||||||
|
assert_equal('not_existsing_host', result[:settings][:options][:host])
|
||||||
|
|
||||||
|
result = EmailHelper::Probe.outbound(
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: 'www.zammad.com',
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'some@example.com',
|
||||||
|
)
|
||||||
|
assert_equal('invalid', result[:result])
|
||||||
|
assert_equal('Connection refused!', result[:message_human])
|
||||||
|
assert_equal('www.zammad.com', result[:settings][:options][:host])
|
||||||
|
|
||||||
|
result = EmailHelper::Probe.outbound(
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: '172.42.42.42',
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'some@example.com',
|
||||||
|
)
|
||||||
|
assert_equal('invalid', result[:result])
|
||||||
|
assert_equal('Host not reachable!', result[:message_human])
|
||||||
|
assert_equal('172.42.42.42', result[:settings][:options][:host])
|
||||||
|
|
||||||
|
# gmail
|
||||||
|
result = EmailHelper::Probe.outbound(
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: 'smtp.gmail.com',
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'some@example.com',
|
||||||
|
)
|
||||||
|
assert_equal('invalid', result[:result])
|
||||||
|
assert_equal('Authentication failed!', result[:message_human])
|
||||||
|
assert_equal('smtp.gmail.com', result[:settings][:options][:host])
|
||||||
|
|
||||||
|
result = EmailHelper::Probe.outbound(
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: 'smtp.gmail.com',
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: 'frank.tailor05@googlemail.com',
|
||||||
|
password: 'password',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'some@example.com',
|
||||||
|
)
|
||||||
|
assert_equal('invalid', result[:result])
|
||||||
|
assert_equal('Authentication failed!', result[:message_human])
|
||||||
|
assert_equal('smtp.gmail.com', result[:settings][:options][:host])
|
||||||
|
|
||||||
|
# dovecot
|
||||||
|
result = EmailHelper::Probe.outbound(
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: 'arber.znuny.com',
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: 'some@example.com',
|
||||||
|
password: 'password',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'some@example.com',
|
||||||
|
)
|
||||||
|
assert_equal('invalid', result[:result])
|
||||||
|
assert_equal('Authentication failed!', result[:message_human])
|
||||||
|
assert_equal('arber.znuny.com', result[:settings][:options][:host])
|
||||||
|
|
||||||
|
# realtest - test I
|
||||||
|
if !ENV['EMAILHELPER_MAILBOX_1']
|
||||||
|
raise "Need EMAILHELPER_MAILBOX_1 as ENV variable like export EMAILHELPER_MAILBOX_1='unittestemailhelper01@znuny.com:somepass'"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
mailbox_user = ENV['EMAILHELPER_MAILBOX_1'].split(':')[0]
|
||||||
|
mailbox_password = ENV['EMAILHELPER_MAILBOX_1'].split(':')[1]
|
||||||
|
user, domain = EmailHelper.parse_email(mailbox_user)
|
||||||
|
result = EmailHelper::Probe.outbound(
|
||||||
|
{
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: 'arber.znuny.com',
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: user,
|
||||||
|
password: mailbox_password,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mailbox_user,
|
||||||
|
)
|
||||||
|
assert_equal('ok', result[:result])
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'zz probe' do
|
||||||
|
|
||||||
|
result = EmailHelper::Probe.full(
|
||||||
|
email: 'invalid_format',
|
||||||
|
password: 'somepass',
|
||||||
|
)
|
||||||
|
assert_equal('invalid', result[:result])
|
||||||
|
assert_not(result[:setting])
|
||||||
|
|
||||||
|
# realtest - test I
|
||||||
|
if !ENV['EMAILHELPER_MAILBOX_1']
|
||||||
|
raise "Need EMAILHELPER_MAILBOX_1 as ENV variable like export EMAILHELPER_MAILBOX_1='unittestemailhelper01@znuny.com:somepass'"
|
||||||
|
end
|
||||||
|
mailbox_user = ENV['EMAILHELPER_MAILBOX_1'].split(':')[0]
|
||||||
|
mailbox_password = ENV['EMAILHELPER_MAILBOX_1'].split(':')[1]
|
||||||
|
|
||||||
|
result = EmailHelper::Probe.full(
|
||||||
|
email: mailbox_user,
|
||||||
|
password: mailbox_password,
|
||||||
|
)
|
||||||
|
assert_equal('ok', result[:result])
|
||||||
|
assert_equal('arber.znuny.com', result[:setting][:inbound][:options][:host])
|
||||||
|
assert_equal('arber.znuny.com', result[:setting][:outbound][:options][:host])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'zz verify' do
|
||||||
|
|
||||||
|
# realtest - test I
|
||||||
|
if !ENV['EMAILHELPER_MAILBOX_1']
|
||||||
|
raise "Need EMAILHELPER_MAILBOX_1 as ENV variable like export EMAILHELPER_MAILBOX_1='unittestemailhelper01@znuny.com:somepass'"
|
||||||
|
end
|
||||||
|
mailbox_user = ENV['EMAILHELPER_MAILBOX_1'].split(':')[0]
|
||||||
|
mailbox_password = ENV['EMAILHELPER_MAILBOX_1'].split(':')[1]
|
||||||
|
user, domain = EmailHelper.parse_email(mailbox_user)
|
||||||
|
result = EmailHelper::Verify.email(
|
||||||
|
inbound: {
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: 'arber.znuny.com',
|
||||||
|
port: 993,
|
||||||
|
ssl: true,
|
||||||
|
user: user,
|
||||||
|
password: mailbox_password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outbound: {
|
||||||
|
adapter: 'smtp',
|
||||||
|
options: {
|
||||||
|
host: 'arber.znuny.com',
|
||||||
|
port: 25,
|
||||||
|
start_tls: true,
|
||||||
|
user: user,
|
||||||
|
password: mailbox_password,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sender: mailbox_user,
|
||||||
|
)
|
||||||
|
assert_equal('ok', result[:result])
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in a new issue