Ticket #1541: mail.diff
File mail.diff, 5.2 KB (added by , 17 years ago) |
---|
-
django/core/mail.py
4 4 5 5 from django.conf import settings 6 6 from email.MIMEText import MIMEText 7 from email.mime.multipart import MIMEMultipart 8 from email.mime.base import MIMEBase 9 from email import Encoders 10 import mimetypes 7 11 from email.Header import Header 8 12 from email.Utils import formatdate 9 13 from email import Charset … … 13 17 import time 14 18 import random 15 19 20 # Default MIME type to use for attachments if it cannot be guessed. 21 DEFAULT_ATTACHMENT_MIME_TYPE = 'application/octet-stream' 22 16 23 # Don't BASE64-encode UTF-8 messages so that we avoid unwanted attention from 17 24 # some spam filters. 18 25 Charset.add_charset('utf-8', Charset.SHORTEST, Charset.QP, 'utf-8') … … 64 71 val = Header(val, settings.DEFAULT_CHARSET) 65 72 MIMEText.__setitem__(self, name, val) 66 73 74 class SafeMIMEMultipart(MIMEMultipart): 75 def __setitem__(self, name, val): 76 "Forbids multi-line headers, to prevent header injection." 77 if '\n' in val or '\r' in val: 78 raise BadHeaderError, "Header values can't contain newlines (got %r for header %r)" % (val, name) 79 if name == 'Subject': 80 val = Header(val, settings.DEFAULT_CHARSET) 81 MIMEMultipart.__setitem__(self, name, val) 82 67 83 class SMTPConnection(object): 68 84 """ 69 85 A wrapper that manages the SMTP network connection. … … 154 170 """ 155 171 A container for email information. 156 172 """ 157 def __init__(self, subject='', body='', from_email=None, to=None, bcc=None, connection=None):173 def __init__(self, subject='', body='', from_email=None, to=None, bcc=None, attachments=None, connection=None): 158 174 self.to = to or [] 159 175 self.bcc = bcc or [] 160 176 self.from_email = from_email or settings.DEFAULT_FROM_EMAIL 161 177 self.subject = subject 162 178 self.body = body 163 179 self.connection = connection 180 self.attachments = attachments or [] 164 181 165 182 def get_connection(self, fail_silently=False): 166 183 if not self.connection: … … 169 186 170 187 def message(self): 171 188 msg = SafeMIMEText(self.body, 'plain', settings.DEFAULT_CHARSET) 189 if self.attachments: 190 body_msg = msg 191 msg = SafeMIMEMultipart() 192 msg.attach(body_msg) 193 for params in self.attachments: 194 msg.attach(self._compile_attachment(*params)) 172 195 msg['Subject'] = self.subject 173 196 msg['From'] = self.from_email 174 197 msg['To'] = ', '.join(self.to) … … 189 212 """Send the email message.""" 190 213 return self.get_connection(fail_silently).send_messages([self]) 191 214 192 def send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None): 215 def attach(self, filename, content, mimetype=None): 216 """Attaches a file with the given filename and content.""" 217 self.attachments.append((filename, content, mimetype)) 218 219 def attach_file(self, path, mimetype=None): 220 """Attaches a file from the filesystem.""" 221 filename = os.path.basename(path) 222 f = open(path, 'rb') 223 content = f.read() 224 f.close() 225 self.attach(filename, content) 226 227 def _compile_attachment(self, filename, content, mimetype): 228 """ 229 Compiles the given attachment to a MIME object and returns the new 230 attachment. 231 """ 232 if mimetype is None: 233 # Guess the mimetype based on the filename if possible. 234 mimetype, xx = mimetypes.guess_type(filename) 235 if mimetype is None: 236 mimetype = DEFAULT_ATTACHMENT_MIME_TYPE 237 basetype, subtype = mimetype.split('/', 1) 238 if basetype == 'text': 239 attachment = SafeMIMEText(content, subtype, settings.DEFAULT_CHARSET) 240 else: 241 # Encode non-text attachments with base64. 242 attachment = MIMEBase(basetype, subtype) 243 attachment.set_payload(content) 244 Encoders.encode_base64(attachment) 245 attachment.add_header('Content-Disposition', 'attachment', filename=filename) 246 return attachment 247 248 def send_mail(subject, message, from_email, recipient_list, attachments=None, fail_silently=False, auth_user=None, auth_password=None): 193 249 """ 194 250 Easy wrapper for sending a single message to a recipient list. All members 195 251 of the recipient list will see the other recipients in the 'To' field. … … 202 258 """ 203 259 connection = SMTPConnection(username=auth_user, password=auth_password, 204 260 fail_silently=fail_silently) 205 return EmailMessage(subject, message, from_email, recipient_list, connection=connection).send()261 return EmailMessage(subject, message, from_email, recipient_list, attachments=attachments, connection=connection).send() 206 262 207 263 def send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None): 208 264 """ … … 233 289 EmailMessage(settings.EMAIL_SUBJECT_PREFIX + subject, message, 234 290 settings.SERVER_EMAIL, [a[1] for a in 235 291 settings.MANAGERS]).send(fail_silently=fail_silently) 236