77from email import message_from_string
88import smtplib
99from django .conf import settings
10+ from django .contrib import messages
1011from django .core .exceptions import ImproperlyConfigured
1112from django .template .loader import render_to_string
1213from django .template import Context ,RequestContext
@@ -169,17 +170,19 @@ def send_mail(request, to, frm, subject, template, context, *args, **kwargs):
169170 txt = render_to_string (template , context , context_instance = mail_context (request ))
170171 return send_mail_text (request , to , frm , subject , txt , * args , ** kwargs )
171172
172-
173- def send_mail_text (request , to , frm , subject , txt , cc = None , extra = None , toUser = False , bcc = None ):
174- """Send plain text message."""
173+ def encode_message (txt ):
175174 if isinstance (txt , unicode ):
176175 msg = MIMEText (txt .encode ('utf-8' ), 'plain' , 'UTF-8' )
177176 else :
178177 msg = MIMEText (txt )
178+ return msg
179+
180+ def send_mail_text (request , to , frm , subject , txt , cc = None , extra = None , toUser = False , bcc = None ):
181+ """Send plain text message."""
182+ msg = encode_message (txt )
179183 send_mail_mime (request , to , frm , subject , msg , cc , extra , toUser , bcc )
180184
181- def send_mail_mime (request , to , frm , subject , msg , cc = None , extra = None , toUser = False , bcc = None ):
182- """Send MIME message with content already filled in."""
185+ def condition_message (to , frm , subject , msg , cc , extra ):
183186 if isinstance (frm , tuple ):
184187 frm = formataddr (frm )
185188 if isinstance (to , list ) or isinstance (to , tuple ):
@@ -200,13 +203,21 @@ def send_mail_mime(request, to, frm, subject, msg, cc=None, extra=None, toUser=F
200203 for k , v in extra .items ():
201204 if v :
202205 msg [k ] = v
206+
207+ def send_mail_mime (request , to , frm , subject , msg , cc = None , extra = None , toUser = False , bcc = None ):
208+ """Send MIME message with content already filled in."""
209+
210+ condition_message (to , frm , subject , msg , cc , extra )
211+
203212 # start debug server with python -m smtpd -n -c DebuggingServer localhost:2025
204213 # then put USING_DEBUG_EMAIL_SERVER=True and EMAIL_HOST='localhost'
205214 # and EMAIL_PORT=2025 in settings_local.py
206215 debugging = getattr (settings , "USING_DEBUG_EMAIL_SERVER" , False ) and settings .EMAIL_HOST == 'localhost' and settings .EMAIL_PORT == 2025
207216
208217 if test_mode or debugging or settings .SERVER_MODE == 'production' :
209- send_smtp (msg , bcc )
218+ with smtp_error_logging (send_smtp ) as logging_send :
219+ with smtp_error_user_warning (logging_send ,request ) as send :
220+ send (msg , bcc )
210221 elif settings .SERVER_MODE == 'test' :
211222 if toUser :
212223 copy_email (msg , to , toUser = True , originalBcc = bcc )
@@ -219,12 +230,12 @@ def send_mail_mime(request, to, frm, subject, msg, cc=None, extra=None, toUser=F
219230 if copy_to and not test_mode and not debugging : # if we're running automated tests, this copy is just annoying
220231 if bcc :
221232 msg ['X-Tracker-Bcc' ]= bcc
222- copy_email (msg , copy_to ,originalBcc = bcc )
233+ with smtp_error_logging (copy_email ) as logging_copy :
234+ with smtp_error_user_warning (logging_copy ,request ) as copy :
235+ copy (msg , copy_to ,originalBcc = bcc )
223236
224- def send_mail_preformatted (request , preformatted , extra = {}, override = {}):
225- """Parse preformatted string containing mail with From:, To:, ...,
226- and send it through the standard IETF mail interface (inserting
227- extra headers as needed)."""
237+ def parse_preformatted (preformatted , extra = {}, override = {}):
238+ """Parse preformatted string containing mail with From:, To:, ...,"""
228239 msg = message_from_string (preformatted .encode ("utf-8" ))
229240
230241 for k , v in override .iteritems ():
@@ -242,7 +253,15 @@ def send_mail_preformatted(request, preformatted, extra={}, override={}):
242253
243254 bcc = msg ['Bcc' ]
244255 del msg ['Bcc' ]
245-
256+
257+ return (msg , headers , bcc )
258+
259+ def send_mail_preformatted (request , preformatted , extra = {}, override = {}):
260+ """Parse preformatted string containing mail with From:, To:, ...,
261+ and send it through the standard IETF mail interface (inserting
262+ extra headers as needed)."""
263+
264+ (msg ,headers ,bcc ) = parse_preformatted (preformatted , extra , override )
246265 send_mail_text (request , msg ['To' ], msg ["From" ], msg ["Subject" ], msg .get_payload (), extra = headers , bcc = bcc )
247266 return msg
248267
@@ -278,6 +297,26 @@ def log_smtp_exception(e):
278297 log (" Traceback: %s" % tb )
279298 return (extype , value , tb )
280299
300+ @contextmanager
301+ def smtp_error_user_warning (thing ,request ):
302+ try :
303+ yield thing
304+ except smtplib .SMTPException as e :
305+ (extype , value , tb ) = log_smtp_exception (e )
306+
307+ warning = "An error occured while sending email with\n "
308+ warning += "Subject: %s\n " % e .original_msg .get ('Subject' ,'[no subject]' )
309+ warning += "To: %s\n " % e .original_msg .get ('To' ,'[no to]' )
310+ warning += "Cc: %s\n " % e .original_msg .get ('Cc' ,'[no cc]' )
311+ if isinstance (e ,SMTPSomeRefusedRecipients ):
312+ warning += e .detailed_refusals ()
313+ else :
314+ warning += "SMTP Exception: %s\n " % extype
315+ warning += "Error Message: %s\n \n " % value
316+ warning += "The message was not delivered to anyone."
317+ messages .warning (request ,warning ,extra_tags = 'preformatted' ,fail_silently = True )
318+ raise
319+
281320@contextmanager
282321def smtp_error_logging (thing ):
283322 try :
@@ -324,9 +363,31 @@ def smtp_error_logging(thing):
324363 %s
325364 --------- END ORIGINAL MESSAGE ---------
326365 """ ) % e .original_msg .as_string ()
366+
367+ send_error_to_secretariat (msg )
368+
369+ def send_error_to_secretariat (raw_msg ):
370+
371+ (parsed_msg , headers , bcc ) = parse_preformatted (raw_msg )
372+ send_msg = encode_message (parsed_msg .get_payload ())
373+ cc = None
374+ condition_message (parsed_msg ['To' ], parsed_msg ['From' ], parsed_msg ['Subject' ], send_msg , cc , headers )
375+
376+ debugging = getattr (settings , "USING_DEBUG_EMAIL_SERVER" , False ) and settings .EMAIL_HOST == 'localhost' and settings .EMAIL_PORT == 2025
377+
378+ try :
379+ if test_mode or debugging or settings .SERVER_MODE == 'production' :
380+ send_smtp (send_msg , bcc )
327381 try :
328- send_mail_preformatted (request = None , preformatted = msg )
329- except smtplib .SMTPException :
330- log ("Exception encountered while sending a ticket to the secretariat" )
331- (extype ,value ) = sys .exc_info ()[:2 ]
332- log ("SMTP Exception: %s : %s" % (extype ,value ))
382+ copy_to = settings .EMAIL_COPY_TO
383+ except AttributeError :
384+ copy_to = "ietf.tracker.archive+%s@gmail.com" % settings .SERVER_MODE
385+ if copy_to and not test_mode and not debugging : # if we're running automated tests, this copy is just annoying
386+ if bcc :
387+ send_msg ['X-Tracker-Bcc' ]= bcc
388+ copy_email (send_msg , copy_to ,originalBcc = bcc )
389+ except smtplib .SMTPException :
390+ log ("Exception encountered while sending a ticket to the secretariat" )
391+ (extype ,value ) = sys .exc_info ()[:2 ]
392+ log ("SMTP Exception: %s : %s" % (extype ,value ))
393+
0 commit comments