SMTP Authentication support for all places where Galaxy sends mail. Use STARTTLS where available, too.

This commit is contained in:
Nate Coraor
2011-06-03 11:25:02 -04:00
parent d00372c8ca
commit 032aa7bdcf
7 changed files with 80 additions and 60 deletions
+2
View File
@@ -76,6 +76,8 @@ class Configuration( object ):
self.mailing_join_addr = kwargs.get('mailing_join_addr',"galaxy-user-join@bx.psu.edu")
self.error_email_to = kwargs.get( 'error_email_to', None )
self.smtp_server = kwargs.get( 'smtp_server', None )
self.smtp_username = kwargs.get( 'smtp_username', None )
self.smtp_password = kwargs.get( 'smtp_password', None )
self.start_job_runners = kwargs.get( 'start_job_runners', None )
# External Service types used in sample tracking
self.external_service_type_config_file = resolve_path( kwargs.get( 'external_service_type_config_file', 'external_service_types_conf.xml' ), self.root )
+5 -23
View File
@@ -1,5 +1,5 @@
import logging, datetime, smtplib
from email.MIMEText import MIMEText
import logging, datetime
from galaxy.util import send_mail
from galaxy.util.json import to_json_string
log = logging.getLogger( __name__ )
@@ -58,35 +58,17 @@ class EmailAction(DefaultJobAction):
@classmethod
def execute(cls, app, sa_session, action, job, replacement_dict):
smtp_server = app.config.smtp_server
if action.action_arguments and action.action_arguments.has_key('host'):
host = action.action_arguments['host']
else:
host = 'usegalaxy.org'
if smtp_server is None:
log.error("Mail is not configured for this galaxy instance. Workflow action aborting after logging mail to info.")
frm = 'galaxy-noreply@%s' % host
to = job.user.email
outdata = ', '.join(ds.dataset.display_name() for ds in job.output_datasets)
msg = MIMEText( "Your Galaxy job generating dataset '%s' is complete as of %s." % (outdata, datetime.datetime.now().strftime( "%I:%M" )))
msg[ 'To' ] = to
msg[ 'From' ] = frm
msg[ 'Subject' ] = "Galaxy notification regarding history '%s'" % (job.history.name)
log.info(msg)
return
# Build the email message
frm = 'galaxy-noreply@%s' % host
to = job.user.email
subject = "Galaxy workflow step notification '%s'" % (job.history.name)
outdata = ', '.join(ds.dataset.display_name() for ds in job.output_datasets)
msg = MIMEText( "Your Galaxy job generating dataset '%s' is complete as of %s." % (outdata, datetime.datetime.now().strftime( "%I:%M" )))
msg[ 'To' ] = to
msg[ 'From' ] = frm
msg[ 'Subject' ] = "Galaxy workflow step notification '%s'" % (job.history.name)
body = "Your Galaxy job generating dataset '%s' is complete as of %s." % (outdata, datetime.datetime.now().strftime( "%I:%M" ))
try:
s = smtplib.SMTP()
s.connect( smtp_server )
s.sendmail( frm, [ to ], msg.as_string() )
s.close()
send_mail( frm, to, subject, body, app.config )
except Exception, e:
log.error("EmailAction PJA Failed, exception: %s" % e)
+2 -6
View File
@@ -15,7 +15,7 @@ from galaxy.util.hash_util import *
from galaxy.web.form_builder import *
from galaxy.model.item_attrs import UsesAnnotations, APIItem
from sqlalchemy.orm import object_session
import os.path, os, errno, codecs, operator, smtplib, socket, pexpect, logging, time
import os.path, os, errno, codecs, operator, socket, pexpect, logging, time
log = logging.getLogger( __name__ )
@@ -1803,12 +1803,8 @@ All samples in state: %(sample_state)s
to = self.notification['email']
frm = 'galaxy-no-reply@' + host
subject = "Galaxy Sample Tracking notification: '%s' sequencing request" % self.name
message = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s" % ( frm, ", ".join( to ), subject, body )
try:
s = smtplib.SMTP()
s.connect( trans.app.config.smtp_server )
s.sendmail( frm, to, message )
s.quit()
util.send_mail( frm, to, subject, body, trans.app.config )
comments = "Email notification sent to %s." % ", ".join( to ).strip().strip( ',' )
except Exception,e:
comments = "Email notification failed. (%s)" % str(e)
+47 -1
View File
@@ -2,7 +2,8 @@
Utility functions used systemwide.
"""
import logging, threading, random, string, re, binascii, pickle, time, datetime, math, re, os, sys, tempfile, stat, grp
import logging, threading, random, string, re, binascii, pickle, time, datetime, math, re, os, sys, tempfile, stat, grp, smtplib
from email.MIMEText import MIMEText
# Older py compatibility
try:
@@ -540,6 +541,51 @@ def nice_size(size):
return "%.1f %s" % (size, word)
return '??? bytes'
def send_mail( frm, to, subject, body, config ):
"""
Sends an email.
"""
msg = MIMEText( body )
msg[ 'To' ] = to
msg[ 'From' ] = frm
msg[ 'Subject' ] = subject
if config.smtp_server is None:
log.error( "Mail is not configured for this Galaxy instance." )
log.info( msg )
return
s = smtplib.SMTP()
s.connect( config.smtp_server )
try:
s.starttls()
log.debug( 'Initiated SSL/TLS connection to SMTP server: %s' % config.smtp_server )
except RuntimeError, e:
log.warning( 'SSL/TLS support is not available to your Python interpreter: %s' % e )
except smtplib.SMTPHeloError, e:
log.error( "The server didn't reply properly to the HELO greeting: %s" % e )
s.close()
raise
except smtplib.SMTPException, e:
log.warning( 'The server does not support the STARTTLS extension: %s' % e )
if config.smtp_username and config.smtp_password:
try:
s.login( config.smtp_username, config.smtp_password )
except smtplib.SMTPHeloError, e:
log.error( "The server didn't reply properly to the HELO greeting: %s" % e )
s.close()
raise
except smtplib.SMTPAuthenticationError, e:
log.error( "The server didn't accept the username/password combination: %s" % e )
s.close()
raise
except smtplib.SMTPError, e:
log.error( "No suitable authentication method was found: %s" % e )
s.close()
raise
if isinstance( to, basestring ):
to = [ to ]
s.sendmail( frm, to, msg.as_string() )
s.quit()
galaxy_root_path = os.path.join(__path__[0], "..","..","..")
# The dbnames list is used in edit attributes and the upload tool
dbnames = read_dbnames( os.path.join( galaxy_root_path, "tool-data", "shared", "ucsc", "builds.txt" ) )
+5 -11
View File
@@ -1,4 +1,4 @@
import logging, os, string, shutil, re, socket, mimetypes, smtplib, urllib, tempfile, zipfile, glob, sys
import logging, os, string, shutil, re, socket, mimetypes, urllib, tempfile, zipfile, glob, sys
from galaxy.web.base.controller import *
from galaxy.web.framework.helpers import time_ago, iff, grids
@@ -10,7 +10,6 @@ from galaxy.util import inflector
from galaxy.model.item_attrs import *
from galaxy.model import LibraryDatasetDatasetAssociation, HistoryDatasetAssociation
from email.MIMEText import MIMEText
import pkg_resources;
pkg_resources.require( "Paste" )
import paste.httpexceptions
@@ -174,7 +173,7 @@ class DatasetInterface( BaseController, UsesAnnotations, UsesHistory, UsesHistor
host = trans.request.host
history_view_link = "%s/history/view?id=%s" % ( str( host ), trans.security.encode_id( hda.history_id ) )
# Build the email message
msg = MIMEText( string.Template( error_report_template )
body = string.Template( error_report_template ) \
.safe_substitute( host=host,
dataset_id=hda.dataset_id,
history_id=hda.history_id,
@@ -189,7 +188,7 @@ class DatasetInterface( BaseController, UsesAnnotations, UsesHistory, UsesHistor
job_info=job.info,
job_traceback=job.traceback,
email=email,
message=message ) )
message=message )
frm = to_address
# Check email a bit
email = email.strip()
@@ -198,15 +197,10 @@ class DatasetInterface( BaseController, UsesAnnotations, UsesHistory, UsesHistor
to = to_address + ", " + email
else:
to = to_address
msg[ 'To' ] = to
msg[ 'From' ] = frm
msg[ 'Subject' ] = "Galaxy tool error report from " + email
subject = "Galaxy tool error report from " + email
# Send it
try:
s = smtplib.SMTP()
s.connect( smtp_server )
s.sendmail( frm, [ to ], msg.as_string() )
s.close()
util.send_mail( frm, to, subject, body, trans.app.config )
return trans.show_ok_message( "Your error report has been sent" )
except Exception, e:
return trans.show_error_message( "An error occurred sending the report by email: %s" % str( e ) )
+11 -18
View File
@@ -5,9 +5,8 @@ from galaxy.web.framework.helpers import time_ago, grids
from galaxy.web.base.controller import *
from galaxy.model.orm import *
from galaxy import util, model
import logging, os, string, re, smtplib, socket, glob
import logging, os, string, re, socket, glob
from random import choice
from email.MIMEText import MIMEText
from galaxy.web.form_builder import *
from galaxy.util.json import from_json_string, to_json_string
from galaxy.web.framework.helpers import iff
@@ -560,15 +559,12 @@ class User( BaseController, UsesFormDefinitions ):
if trans.app.config.smtp_server is None:
error = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed because mail is not configured for this Galaxy instance."
else:
msg = MIMEText( 'Join Mailing list.\n' )
to = msg[ 'To' ] = trans.app.config.mailing_join_addr
frm = msg[ 'From' ] = email
msg[ 'Subject' ] = 'Join Mailing List'
body = 'Join Mailing list.\n'
to = trans.app.config.mailing_join_addr
frm = email
subject = 'Join Mailing List'
try:
s = smtplib.SMTP()
s.connect( trans.app.config.smtp_server )
s.sendmail( frm, [ to ], msg.as_string() )
s.close()
util.send_mail( frm, to, subject, body, trans.app.config )
except:
error = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed."
if not error and not is_admin:
@@ -888,15 +884,12 @@ class User( BaseController, UsesFormDefinitions ):
host = trans.request.host.split(':')[0]
if host == 'localhost':
host = socket.getfqdn()
msg = MIMEText( 'Your password on %s has been reset to:\n\n %s\n' % ( host, new_pass ) )
to = msg[ 'To' ] = email
frm = msg[ 'From' ] = 'galaxy-no-reply@' + host
msg[ 'Subject' ] = 'Galaxy Password Reset'
body = 'Your password on %s has been reset to:\n\n %s\n' % ( host, new_pass )
to = email
frm = 'galaxy-no-reply@' + host
subject = 'Galaxy Password Reset'
try:
s = smtplib.SMTP()
s.connect( trans.app.config.smtp_server )
s.sendmail( frm, [ to ], msg.as_string() )
s.close()
util.send_mail( frm, to, subject, body, trans.app.config )
reset_user.set_password_cleartext( new_pass )
trans.sa_session.add( reset_user )
trans.sa_session.flush()
+8 -1
View File
@@ -161,9 +161,16 @@ paste.app_factory = galaxy.web.buildapp:app_factory
# Galaxy sends mail for various things: Subscribing users to the mailing list
# if they request it, emailing password resets, notification from the Galaxy
# Sample Tracking system, and reporting dataset errors. To do this, it needs
# to send mail through an SMTP server, which you may define here.
# to send mail through an SMTP server, which you may define here (host:port).
# Galaxy will automatically try STARTTLS but will continue upon failure.
#smtp_server = None
# If your SMTP server requires a username and password, you can provide them
# here (password in cleartext here, but if your server supports STARTTLS it
# will be sent over the network encrypted).
#smtp_username = None
#smtp_password = None
# On the user registration form, users may choose to join the mailing list.
# This is the address of the list they'll be subscribed to.
#mailing_join_addr = galaxy-user-join@bx.psu.edu