import base64
import logging
import re
+from email.utils import formataddr
from urllib import urlencode
from urlparse import urljoin
# 2. if 'partner' is specified, but no related document: Partner Name <email>
# 3; fallback on mail.email_to that we split to have an email addresses list
if partner and mail.record_name:
- sanitized_record_name = re.sub(r'[^\w+.]+', '-', mail.record_name)
- email_to = [_('"Followers of %s" <%s>') % (sanitized_record_name, partner.email)]
+ email_to = [formataddr((_('Followers of %s') % mail.record_name, partner.email))]
elif partner:
- email_to = ['%s <%s>' % (partner.name, partner.email)]
+ email_to = [formataddr((partner.name, partner.email))]
else:
email_to = tools.email_split(mail.email_to)
:return: True
"""
ir_mail_server = self.pool.get('ir.mail_server')
-
+ ir_attachment = self.pool['ir.attachment']
+
for mail in self.browse(cr, SUPERUSER_ID, ids, context=context):
try:
- # handle attachments
- attachments = []
- for attach in mail.attachment_ids:
- attachments.append((attach.datas_fname, base64.b64decode(attach.datas)))
+ # load attachment binary data with a separate read(), as prefetching all
+ # `datas` (binary field) could bloat the browse cache, triggerring
+ # soft/hard mem limits with temporary data.
+ attachment_ids = [a.id for a in mail.attachment_ids]
+ attachments = [(a['datas_fname'], base64.b64decode(a['datas']))
+ for a in ir_attachment.read(cr, SUPERUSER_ID, attachment_ids,
+ ['datas_fname', 'datas'])]
# specific behavior to customize the send email for notified partners
email_list = []
if mail.email_to:
subtype='html',
subtype_alternative='plain',
headers=headers)
- res = ir_mail_server.send_email(cr, uid, msg,
+ try:
+ res = ir_mail_server.send_email(cr, uid, msg,
mail_server_id=mail.mail_server_id.id,
context=context)
-
+ except AssertionError as error:
+ if error.message == ir_mail_server.NO_VALID_RECIPIENT:
+ # No valid recipient found for this particular
+ # mail item -> ignore error to avoid blocking
+ # delivery to next recipients, if any. If this is
+ # the only recipient, the mail will show as failed.
+ _logger.warning("Ignoring invalid recipients for mail.mail %s: %s",
+ mail.message_id, email.get('email_to'))
+ else:
+ raise
if res:
mail.write({'state': 'sent', 'message_id': res})
mail_sent = True
# /!\ can't use mail.state here, as mail.refresh() will cause an error
# see revid:odo@openerp.com-20120622152536-42b2s28lvdv3odyr in 6.1
if mail_sent:
+ _logger.info('Mail with ID %r and Message-Id %r successfully sent', mail.id, mail.message_id)
self._postprocess_sent_message(cr, uid, mail, context=context)
except MemoryError:
# prevent catching transient MemoryErrors, bubble up to notify user or abort cron job
# instead of marking the mail as failed
+ _logger.exception('MemoryError while processing mail with ID %r and Msg-Id %r. '\
+ 'Consider raising the --limit-memory-hard startup option',
+ mail.id, mail.message_id)
raise
except Exception as e:
_logger.exception('failed sending mail.mail %s', mail.id)