2019-05-03 08:17:27 +10:00
# frozen_string_literal: true
2016-01-19 00:57:55 +01:00
def process_popmail ( popmail )
begin
mail_string = popmail . pop
Email :: Receiver . new ( mail_string ) . process
rescue StandardError
putc "!"
else
putc "."
end
end
2021-05-20 23:37:17 -04:00
desc "use this task to import a mailbox into Discourse"
2016-01-19 00:57:55 +01:00
task "emails:import" => :environment do
begin
unless SiteSetting . email_in
puts "ERROR: you should enable the 'email_in' site setting before running this task"
exit ( 1 )
end
address = ENV [ "ADDRESS" ]. presence || "pop.gmail.com"
port = ( ENV [ "PORT" ]. presence || 995 ) . to_i
ssl = ( ENV [ "SSL" ]. presence || "1" ) == "1"
username = ENV [ "USERNAME" ]. presence
password = ENV [ "PASSWORD" ]. presence
if username . blank?
puts "ERROR: expecting USERNAME=<username> rake emails:import"
exit ( 2 )
elsif password . blank?
puts "ERROR: expecting PASSWORD=<password> rake emails:import"
exit ( 3 )
end
RateLimiter . disable
mails_left = 1
pop3 = Net :: POP3 . new ( address , port )
2019-09-11 18:43:02 +02:00
pop3 . enable_ssl ( max_version : OpenSSL :: SSL :: TLS1_2_VERSION ) if ssl
2016-01-19 00:57:55 +01:00
while mails_left > 0
pop3 . start ( username , password ) do | pop |
pop . delete_all { | p | process_popmail ( p ) }
mails_left = pop . n_mails
end
end
puts "Done"
rescue Net :: POPAuthenticationError
puts "AUTH EXCEPTION: please make sure your credentials are correct."
exit ( 10 )
ensure
RateLimiter . enable
end
end
2018-05-13 05:15:15 -07:00
2018-07-31 06:45:59 +02:00
desc "Check if SMTP connection is successful and send test message"
2018-05-13 05:15:15 -07:00
task "emails:test" , [ :email ] => [ :environment ] do | _ , args |
email = args [ :email ]
2018-07-31 06:45:59 +02:00
message = "OK"
2025-10-27 15:34:11 -04:00
def textwidth
@textwidth ||=
begin
IO . console . winsize [ 1 ]
rescue StandardError
80
end
end
def make_warning_message ( warning )
<<~ EOT
#{" WARNING ".center(textwidth, "=")}
#{warning}\
#{"=" * textwidth}
EOT
end
def make_error_message ( error , solution )
<<~ EOT
#{" ERROR ".center(textwidth, "=")}
#{error}\
#{" SOLUTION ".center(textwidth, "=")}
#{solution}\
#{"=" * textwidth}
EOT
end
2018-07-31 06:45:59 +02:00
begin
2018-07-31 14:50:02 +10:00
smtp = Discourse :: Application . config . action_mailer . smtp_settings
2018-07-31 06:45:59 +02:00
2025-10-27 15:34:11 -04:00
puts make_warning_message ( <<~ WARN ) + " \n " if smtp [ :address ]. match ( /smtp\.gmail\.com/ )
Sending mail with Gmail is a violation of their terms of service .
2018-07-31 06:45:59 +02:00
2025-10-27 15:34:11 -04:00
Sending with G Suite might work , but it is not recommended .
For further information see : https : //me ta . discourse . org / t / 62931
2018-07-31 06:45:59 +02:00
2025-10-27 15:34:11 -04:00
Current settings :
#{smtp.compact}
2018-07-31 06:45:59 +02:00
2025-10-27 15:34:11 -04:00
Continuing …
WARN
2018-07-31 06:45:59 +02:00
2025-10-27 15:34:11 -04:00
puts "Testing sending to #{ email } using #{ smtp [ :address ] } : #{ smtp [ :port ] } , username: #{ smtp [ :user_name ] || "(none)" } with #{ smtp [ :authentication ] || "no" } auth."
2018-07-31 06:45:59 +02:00
2022-01-04 08:30:48 +10:00
# We are not formatting the messages using EmailSettingsExceptionHandler here
# because we are doing custom messages in the rake task with more details.
EmailSettingsValidator . validate_smtp (
host : smtp [ :address ] ,
port : smtp [ :port ] ,
domain : smtp [ :domain ] || "localhost" ,
username : smtp [ :user_name ] ,
password : smtp [ :password ] ,
2024-04-19 12:52:22 -04:00
authentication : smtp [ :authentication ] ,
2022-01-04 08:30:48 +10:00
)
2018-07-31 06:45:59 +02:00
rescue Exception => e
2025-10-27 15:34:11 -04:00
message =
case e
when ArgumentError
make_error_message ( <<~ ERR , <<~ SOL )
#{e.class}: #{e.message.strip}
ERR
The combination of SMTP parameters is invalid - see the above error message for the reason .
If you need assistance , please report the relevant SMTP environment variables
and the exact error message above to https : //me ta . discourse . org /
SOL
when Net :: SMTPAuthenticationError
case e . message
when /530.*STARTTLS/
make_error_message ( <<~ ERR , <<~ SOL )
Your mail server has refused to accept credentials over an unencrypted connection .
#{e.class}: #{e.message.strip}
ERR
If you have disabled STARTTLS ( DISCOURSE_SMTP_ENABLE_START_TLS = false ), remove it .
SOL
else
make_error_message ( <<~ ERR , <<~ SOL )
Your mail server has refused your credentials as invalid :
#{e.class}: #{e.message.strip}
ERR
Check your credentials for the mail server to verify they are correct :
Username : #{smtp[:user_name]}
Password : #{smtp[:password][..3]}… (truncated to four characters)
SOL
end
when Errno :: ECONNREFUSED
make_error_message ( <<~ ERR , <<~ SOL )
Connection to port #{smtp[:port]} failed:
#{e.class}: #{e.message.strip}
ERR
Your server has outgoing SMTP traffic blocked , or your connection attempt is explicitly blocked by your network .
If you are using a external SMTP service ( such as Mailgun or Sendgrid ),
review their service documentation to find an alternative port such as 2525 .
SOL
when Errno :: ENETUNREACH
make_error_message ( <<~ ERR , <<~ SOL )
Connection to port #{smtp[:port]} failed:
#{e.class}: #{e.message.strip}
ERR
Check your server connectivity . The server may actually be unreachable , or you may have chosen the
wrong port , or a network problem is preventing access from the Docker container .
SOL
when Net :: OpenTimeout
make_error_message ( <<~ ERR , <<~ SOL )
Connection timeout while making the initial connection
#{e.class}: #{e.message.strip}
ERR
The server may not actually be reachable , or your traffic may be silently dropped .
If you are using a external SMTP service ( such as Mailgun or Sendgrid ),
review their service documentation to find an alternative port such as 2525 .
SOL
when Socket :: ResolutionError
make_error_message ( <<~ ERR , <<~ SOL )
SMTP server not found!
#{e.class}: #{e.message.strip}
ERR
2018-07-31 14:50:02 +10:00
The most likely problem is that the host name of your SMTP server is incorrect .
Check it and try again .
2025-10-27 15:34:11 -04:00
SOL
when OpenSSL :: SSL :: SSLError
case e . message
when /certificate verify failed/
make_error_message ( <<~ ERR , <<~ SOL )
Encountered a certificate verification error while connecting to the mail server .
#{e.class}: #{e.message.strip}
ERR
Check the SMTP server certificate . If the certificate is self - signed or from a private authority ,
consider setting DISCOURSE_SMTP_OPENSSL_VERIFY_MODE = none to disable verification .
If you need assistance , please report the relevant SMTP environment variables
and the exact error message above to https : //me ta . discourse . org /
SOL
else
make_error_message ( <<~ ERR , <<~ SOL )
OpenSSL error encountered :
#{e.class}: #{e.message.strip}
ERR
An unexpected error from openssl was encountered . Review the above output for clues .
If you need assistance , please report the relevant SMTP environment variables
and the exact error message above to https : //me ta . discourse . org /
SOL
end
else
make_error_message ( <<~ ERR , <<~ SOL )
UNKNOWN ERROR !
#{e.class}: #{e.message.strip}
ERR
2018-07-31 14:50:02 +10:00
This is not a common error . No recommended solution exists!
2018-07-31 06:45:59 +02:00
2019-01-16 21:41:10 -05:00
Please report the exact error message above to https : //me ta . discourse . org /
( And a solution , if you find one! )
2025-10-27 15:34:11 -04:00
SOL
end
2018-07-31 06:45:59 +02:00
end
2025-10-27 15:34:11 -04:00
2018-07-31 06:45:59 +02:00
if message == "OK"
puts "SMTP server connection successful."
else
puts message
2025-10-27 15:34:11 -04:00
exit 1
2018-07-31 06:45:59 +02:00
end
2025-10-27 15:34:11 -04:00
2018-07-31 06:45:59 +02:00
begin
2025-10-27 15:34:11 -04:00
puts "Sending to #{ email } …"
2021-07-09 11:14:18 -07:00
email_log = Email :: Sender . new ( TestMailer . send_test ( email ), :test_message ) . send
case email_log
when SkippedEmailLog
2025-10-27 15:34:11 -04:00
puts make_error_message ( <<~ ERR , <<~ SOL )
2021-07-09 11:14:18 -07:00
Mail was not sent .
2025-10-27 15:34:11 -04:00
Reason : #{email_log.reason.strip}
ERR
Review the reason for the failure and address it with the server owner .
SOL
2021-07-09 11:14:18 -07:00
when EmailLog
2022-02-28 20:50:55 +01:00
puts <<~ TEXT
2021-07-09 11:14:18 -07:00
Mail accepted by SMTP server .
Message - ID : #{email_log.message_id}
If you do not receive the message , check your SPAM folder
or test again using a service like http : // www . mail - tester . com /.
If the message is not delivered it is not a problem with Discourse .
Check the SMTP server logs for the above Message ID to see why it
failed to deliver the message .
2022-02-28 20:50:55 +01:00
TEXT
2021-07-09 11:14:18 -07:00
when nil
2025-10-27 15:34:11 -04:00
puts make_error_message ( <<~ ERR , <<~ SOL )
2021-07-09 11:14:18 -07:00
Mail was not sent .
2025-10-27 15:34:11 -04:00
ERR
2021-07-09 11:14:18 -07:00
Verify the status of the `disable_emails` site setting .
2025-10-27 15:34:11 -04:00
SOL
2021-07-09 11:14:18 -07:00
else
2025-10-27 15:34:11 -04:00
puts make_error_message ( <<~ ERR , <<~ SOL )
2021-07-09 11:14:18 -07:00
SCRIPT BUG : Got back a #{email_log.class}
#{email_log.inspect}
2025-10-27 15:34:11 -04:00
ERR
2021-07-09 11:14:18 -07:00
Mail may or may not have been sent . Check the destination mailbox .
2025-10-27 15:34:11 -04:00
Post this output to https : //me ta . discourse . org / for assistance .
SOL
2021-07-09 11:14:18 -07:00
end
2025-10-27 15:34:11 -04:00
rescue => e
puts make_error_message ( <<~ ERR , <<~ SOL )
Sending mail failed :
#{e.class}: #{e.message.strip}
ERR
Post this output to https : //me ta . discourse . org / for assistance .
SOL
2021-07-09 11:14:18 -07:00
end
2018-07-31 06:45:59 +02:00
2025-10-27 15:34:11 -04:00
puts make_warning_message ( <<~ WARN ) if SiteSetting . disable_emails != "no"
2021-07-09 11:14:18 -07:00
The `disable_emails` site setting is currently set to #{SiteSetting.disable_emails}.
Consider changing it to 'no' before performing any further troubleshooting .
2025-10-27 15:34:11 -04:00
WARN
2018-05-13 05:15:15 -07:00
end
2023-05-19 10:33:48 +02:00
desc "run this to fix users associated to emails mirrored from a mailman mailing list"
task "emails:fix_mailman_users" => :environment do
if ! SiteSetting . enable_staged_users
puts "Please enable staged users first"
exit 1
end
def find_or_create_user ( email , name )
user = nil
User . transaction do
unless user = User . find_by_email ( email )
username = UserNameSuggester . sanitize_username ( name ) if name . present?
username = UserNameSuggester . suggest ( username . presence || email )
name = name . presence || User . suggest_name ( email )
begin
user = User . create! ( email : email , username : username , name : name , staged : true )
rescue PG :: UniqueViolation , ActiveRecord :: RecordNotUnique , ActiveRecord :: RecordInvalid
end
end
end
user
end
IncomingEmail
. includes ( :user , :post )
. where ( "raw LIKE '%X-Mailman-Version: %'" )
. find_each do | ie |
2024-05-27 12:27:13 +02:00
next if ie . post . blank?
2023-05-19 10:33:48 +02:00
mail = Mail . new ( ie . raw )
email , name = Email :: Receiver . extract_email_address_and_name_from_mailman ( mail )
if email . blank? || email == ie . user . email
putc "."
elsif new_owner = find_or_create_user ( email , name )
PostOwnerChanger . new (
post_ids : [ ie . post_id ] ,
topic_id : ie . post . topic_id ,
new_owner : new_owner ,
acting_user : Discourse . system_user ,
skip_revision : true ,
) . change_owner!
putc "#"
else
putc "X"
end
end
nil
end