2012-08-22 07:45:45 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
##############################################################################
|
|
|
|
#
|
|
|
|
# OpenERP, Open Source Management Solution
|
|
|
|
# Copyright (C) 2010-today OpenERP SA (<http://www.openerp.com>)
|
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU Affero General Public License as
|
|
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
|
|
# License, or (at your option) any later version
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU Affero General Public License for more details
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
|
|
#
|
|
|
|
##############################################################################
|
|
|
|
|
2012-08-15 18:44:03 +00:00
|
|
|
import base64
|
|
|
|
import logging
|
2014-08-12 11:40:45 +00:00
|
|
|
from email.utils import formataddr
|
2013-01-04 12:57:54 +00:00
|
|
|
from urlparse import urljoin
|
2012-08-15 18:44:03 +00:00
|
|
|
|
2014-07-06 14:44:26 +00:00
|
|
|
from openerp import api, tools
|
2012-09-14 11:51:07 +00:00
|
|
|
from openerp import SUPERUSER_ID
|
2013-06-04 15:15:08 +00:00
|
|
|
from openerp.addons.base.ir.ir_mail_server import MailDeliveryException
|
2012-12-06 14:56:32 +00:00
|
|
|
from openerp.osv import fields, osv
|
2014-06-20 14:34:27 +00:00
|
|
|
from openerp.tools.safe_eval import safe_eval as eval
|
2012-12-06 14:56:32 +00:00
|
|
|
from openerp.tools.translate import _
|
2012-08-15 18:44:03 +00:00
|
|
|
|
2012-08-22 01:09:47 +00:00
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
2012-09-12 12:01:44 +00:00
|
|
|
|
2012-08-15 17:08:22 +00:00
|
|
|
class mail_mail(osv.Model):
|
2012-08-31 09:31:39 +00:00
|
|
|
""" Model holding RFC2822 email messages to send. This model also provides
|
|
|
|
facilities to queue and send new email messages. """
|
2012-08-15 17:08:22 +00:00
|
|
|
_name = 'mail.mail'
|
|
|
|
_description = 'Outgoing Mails'
|
2012-08-16 09:26:16 +00:00
|
|
|
_inherits = {'mail.message': 'mail_message_id'}
|
2012-08-30 08:51:16 +00:00
|
|
|
_order = 'id desc'
|
2014-05-06 10:46:21 +00:00
|
|
|
_rec_name = 'subject'
|
2012-08-30 08:51:16 +00:00
|
|
|
|
2012-08-15 17:08:22 +00:00
|
|
|
_columns = {
|
2014-08-07 10:50:13 +00:00
|
|
|
'mail_message_id': fields.many2one('mail.message', 'Message', required=True, ondelete='cascade', auto_join=True),
|
2012-08-15 17:08:22 +00:00
|
|
|
'state': fields.selection([
|
2012-08-15 19:34:06 +00:00
|
|
|
('outgoing', 'Outgoing'),
|
|
|
|
('sent', 'Sent'),
|
|
|
|
('received', 'Received'),
|
|
|
|
('exception', 'Delivery Failed'),
|
|
|
|
('cancel', 'Cancelled'),
|
2014-07-06 14:44:26 +00:00
|
|
|
], 'Status', readonly=True, copy=False),
|
2012-08-15 17:08:22 +00:00
|
|
|
'auto_delete': fields.boolean('Auto Delete',
|
|
|
|
help="Permanently delete this email after sending it, to save space"),
|
2012-08-16 09:26:16 +00:00
|
|
|
'references': fields.text('References', help='Message references, such as identifiers of previous messages', readonly=1),
|
2013-02-25 16:48:57 +00:00
|
|
|
'email_to': fields.text('To', help='Message recipients (emails)'),
|
2013-03-14 12:06:11 +00:00
|
|
|
'recipient_ids': fields.many2many('res.partner', string='To (Partners)'),
|
2012-08-30 17:44:52 +00:00
|
|
|
'email_cc': fields.char('Cc', help='Carbon copy message recipients'),
|
2012-08-30 08:51:16 +00:00
|
|
|
'body_html': fields.text('Rich-text Contents', help="Rich-text/HTML message"),
|
2014-07-06 14:44:26 +00:00
|
|
|
'headers': fields.text('Headers', copy=False),
|
2012-09-05 15:19:50 +00:00
|
|
|
# Auto-detected based on create() - if 'mail_message_id' was passed then this mail is a notification
|
2012-09-12 12:01:44 +00:00
|
|
|
# and during unlink() we will not cascade delete the parent and its attachments
|
2013-03-19 09:18:44 +00:00
|
|
|
'notification': fields.boolean('Is Notification',
|
2013-08-06 15:11:43 +00:00
|
|
|
help='Mail has been created to notify people of an existing mail.message'),
|
2012-08-15 17:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_defaults = {
|
2012-08-15 18:44:03 +00:00
|
|
|
'state': 'outgoing',
|
2012-08-15 17:08:22 +00:00
|
|
|
}
|
|
|
|
|
2013-02-01 09:13:03 +00:00
|
|
|
def default_get(self, cr, uid, fields, context=None):
|
|
|
|
# protection for `default_type` values leaking from menu action context (e.g. for invoices)
|
|
|
|
# To remove when automatic context propagation is removed in web client
|
2014-11-07 11:34:04 +00:00
|
|
|
if context and context.get('default_type') and context.get('default_type') not in self._all_columns['type'].column.selection:
|
2013-02-25 16:48:57 +00:00
|
|
|
context = dict(context, default_type=None)
|
2013-02-01 09:13:03 +00:00
|
|
|
return super(mail_mail, self).default_get(cr, uid, fields, context=context)
|
|
|
|
|
2012-09-05 15:19:50 +00:00
|
|
|
def create(self, cr, uid, values, context=None):
|
2013-03-18 15:02:52 +00:00
|
|
|
# notification field: if not set, set if mail comes from an existing mail.message
|
2012-09-05 15:19:50 +00:00
|
|
|
if 'notification' not in values and values.get('mail_message_id'):
|
|
|
|
values['notification'] = True
|
2013-08-27 13:30:58 +00:00
|
|
|
return super(mail_mail, self).create(cr, uid, values, context=context)
|
2012-09-05 15:19:50 +00:00
|
|
|
|
|
|
|
def unlink(self, cr, uid, ids, context=None):
|
|
|
|
# cascade-delete the parent message for all mails that are not created for a notification
|
2012-09-12 12:01:44 +00:00
|
|
|
ids_to_cascade = self.search(cr, uid, [('notification', '=', False), ('id', 'in', ids)])
|
2012-09-05 15:19:50 +00:00
|
|
|
parent_msg_ids = [m.mail_message_id.id for m in self.browse(cr, uid, ids_to_cascade, context=context)]
|
2012-09-12 12:01:44 +00:00
|
|
|
res = super(mail_mail, self).unlink(cr, uid, ids, context=context)
|
2012-09-05 15:19:50 +00:00
|
|
|
self.pool.get('mail.message').unlink(cr, uid, parent_msg_ids, context=context)
|
|
|
|
return res
|
|
|
|
|
2012-08-15 17:08:22 +00:00
|
|
|
def mark_outgoing(self, cr, uid, ids, context=None):
|
2012-09-12 12:01:44 +00:00
|
|
|
return self.write(cr, uid, ids, {'state': 'outgoing'}, context=context)
|
2012-08-15 17:08:22 +00:00
|
|
|
|
|
|
|
def cancel(self, cr, uid, ids, context=None):
|
2012-09-12 12:01:44 +00:00
|
|
|
return self.write(cr, uid, ids, {'state': 'cancel'}, context=context)
|
2012-08-15 17:08:22 +00:00
|
|
|
|
2014-07-06 14:44:26 +00:00
|
|
|
@api.cr_uid
|
2012-08-15 17:08:22 +00:00
|
|
|
def process_email_queue(self, cr, uid, ids=None, context=None):
|
|
|
|
"""Send immediately queued messages, committing after each
|
|
|
|
message is sent - this is not transactional and should
|
|
|
|
not be called during another transaction!
|
|
|
|
|
|
|
|
:param list ids: optional list of emails ids to send. If passed
|
|
|
|
no search is performed, and these ids are used
|
|
|
|
instead.
|
|
|
|
:param dict context: if a 'filters' key is present in context,
|
|
|
|
this value will be used as an additional
|
|
|
|
filter to further restrict the outgoing
|
|
|
|
messages to send (by default all 'outgoing'
|
|
|
|
messages are sent).
|
|
|
|
"""
|
|
|
|
if context is None:
|
|
|
|
context = {}
|
|
|
|
if not ids:
|
2013-06-14 13:24:18 +00:00
|
|
|
filters = [('state', '=', 'outgoing')]
|
2012-08-15 17:08:22 +00:00
|
|
|
if 'filters' in context:
|
|
|
|
filters.extend(context['filters'])
|
|
|
|
ids = self.search(cr, uid, filters, context=context)
|
|
|
|
res = None
|
|
|
|
try:
|
|
|
|
# Force auto-commit - this is meant to be called by
|
|
|
|
# the scheduler, and we can't allow rolling back the status
|
|
|
|
# of previously sent emails!
|
|
|
|
res = self.send(cr, uid, ids, auto_commit=True, context=context)
|
|
|
|
except Exception:
|
|
|
|
_logger.exception("Failed processing mail queue")
|
|
|
|
return res
|
|
|
|
|
2014-03-18 16:41:17 +00:00
|
|
|
def _postprocess_sent_message(self, cr, uid, mail, context=None, mail_sent=True):
|
2012-09-05 15:19:50 +00:00
|
|
|
"""Perform any post-processing necessary after sending ``mail``
|
2012-08-15 17:08:22 +00:00
|
|
|
successfully, including deleting it completely along with its
|
2012-09-05 15:19:50 +00:00
|
|
|
attachment if the ``auto_delete`` flag of the mail was set.
|
2012-09-12 12:01:44 +00:00
|
|
|
Overridden by subclasses for extra post-processing behaviors.
|
2012-08-15 17:08:22 +00:00
|
|
|
|
2012-09-05 15:19:50 +00:00
|
|
|
:param browse_record mail: the mail that was just sent
|
2012-08-15 17:08:22 +00:00
|
|
|
:return: True
|
|
|
|
"""
|
2014-04-25 12:27:26 +00:00
|
|
|
if mail_sent and mail.auto_delete:
|
2012-09-14 11:51:07 +00:00
|
|
|
# done with SUPERUSER_ID to avoid giving large unlink access rights
|
|
|
|
self.unlink(cr, SUPERUSER_ID, [mail.id], context=context)
|
2012-08-15 17:08:22 +00:00
|
|
|
return True
|
|
|
|
|
2013-04-17 12:22:25 +00:00
|
|
|
#------------------------------------------------------
|
|
|
|
# mail_mail formatting, tools and send mechanism
|
|
|
|
#------------------------------------------------------
|
|
|
|
|
|
|
|
def _get_partner_access_link(self, cr, uid, mail, partner=None, context=None):
|
2014-03-21 17:14:55 +00:00
|
|
|
"""Generate URLs for links in mails: partner has access (is user):
|
2014-03-21 12:30:29 +00:00
|
|
|
link to action_mail_redirect action that will redirect to doc or Inbox """
|
2014-03-05 17:36:10 +00:00
|
|
|
if context is None:
|
|
|
|
context = {}
|
2013-04-17 12:22:25 +00:00
|
|
|
if partner and partner.user_ids:
|
2014-12-15 16:34:21 +00:00
|
|
|
base_url = self.pool.get('ir.config_parameter').get_param(cr, SUPERUSER_ID, 'web.base.url')
|
2014-05-20 11:10:44 +00:00
|
|
|
mail_model = mail.model or 'mail.thread'
|
|
|
|
url = urljoin(base_url, self.pool[mail_model]._get_access_link(cr, uid, mail, partner, context=context))
|
2014-08-29 11:08:06 +00:00
|
|
|
return "<span class='oe_mail_footer_access'><small>%(access_msg)s <a style='color:inherit' href='%(portal_link)s'>%(portal_msg)s</a></small></span>" % {
|
|
|
|
'access_msg': _('about') if mail.record_name else _('access'),
|
|
|
|
'portal_link': url,
|
|
|
|
'portal_msg': '%s %s' % (context.get('model_name', ''), mail.record_name) if mail.record_name else _('your messages'),
|
|
|
|
}
|
2013-04-17 12:22:25 +00:00
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
2012-09-12 15:53:00 +00:00
|
|
|
def send_get_mail_subject(self, cr, uid, mail, force=False, partner=None, context=None):
|
2014-03-21 17:14:55 +00:00
|
|
|
"""If subject is void, set the subject as 'Re: <Resource>' or
|
|
|
|
'Re: <mail.parent_id.subject>'
|
2012-09-12 13:38:43 +00:00
|
|
|
|
2012-09-13 15:48:44 +00:00
|
|
|
:param boolean force: force the subject replacement
|
2012-09-12 13:38:43 +00:00
|
|
|
"""
|
2013-05-15 13:33:32 +00:00
|
|
|
if (force or not mail.subject) and mail.record_name:
|
2013-02-14 12:39:25 +00:00
|
|
|
return 'Re: %s' % (mail.record_name)
|
2013-05-15 13:33:32 +00:00
|
|
|
elif (force or not mail.subject) and mail.parent_id and mail.parent_id.subject:
|
|
|
|
return 'Re: %s' % (mail.parent_id.subject)
|
2012-08-31 09:31:39 +00:00
|
|
|
return mail.subject
|
|
|
|
|
2013-03-15 11:04:21 +00:00
|
|
|
def send_get_mail_body(self, cr, uid, mail, partner=None, context=None):
|
2014-03-21 17:14:55 +00:00
|
|
|
"""Return a specific ir_email body. The main purpose of this method
|
|
|
|
is to be inherited to add custom content depending on some module."""
|
2013-03-15 11:04:21 +00:00
|
|
|
body = mail.body_html
|
|
|
|
|
2014-08-14 09:29:00 +00:00
|
|
|
# generate access links for notifications or emails linked to a specific document with auto threading
|
|
|
|
link = None
|
|
|
|
if mail.notification or (mail.model and mail.res_id and not mail.no_auto_thread):
|
|
|
|
link = self._get_partner_access_link(cr, uid, mail, partner, context=context)
|
2013-04-17 12:22:25 +00:00
|
|
|
if link:
|
|
|
|
body = tools.append_content_to_html(body, link, plaintext=False, container_tag='div')
|
2013-01-04 12:57:54 +00:00
|
|
|
return body
|
2012-09-12 13:38:43 +00:00
|
|
|
|
2014-03-21 17:14:55 +00:00
|
|
|
def send_get_mail_to(self, cr, uid, mail, partner=None, context=None):
|
|
|
|
"""Forge the email_to with the following heuristic:
|
2014-08-13 18:46:47 +00:00
|
|
|
- if 'partner', recipient specific (Partner Name <email>)
|
2014-03-21 17:14:55 +00:00
|
|
|
- else fallback on mail.email_to splitting """
|
2014-06-20 11:38:22 +00:00
|
|
|
if partner:
|
2014-08-12 14:27:57 +00:00
|
|
|
email_to = [formataddr((partner.name, partner.email))]
|
2013-04-03 12:10:22 +00:00
|
|
|
else:
|
|
|
|
email_to = tools.email_split(mail.email_to)
|
2014-03-21 17:14:55 +00:00
|
|
|
return email_to
|
|
|
|
|
|
|
|
def send_get_email_dict(self, cr, uid, mail, partner=None, context=None):
|
|
|
|
"""Return a dictionary for specific email values, depending on a
|
|
|
|
partner, or generic to the whole recipients given by mail.email_to.
|
2013-04-03 12:10:22 +00:00
|
|
|
|
2014-03-21 17:14:55 +00:00
|
|
|
:param browse_record mail: mail.mail browse_record
|
|
|
|
:param browse_record partner: specific recipient partner
|
|
|
|
"""
|
|
|
|
body = self.send_get_mail_body(cr, uid, mail, partner=partner, context=context)
|
|
|
|
body_alternative = tools.html2plaintext(body)
|
2014-06-12 11:45:21 +00:00
|
|
|
res = {
|
2012-09-12 13:38:43 +00:00
|
|
|
'body': body,
|
|
|
|
'body_alternative': body_alternative,
|
2014-03-21 17:14:55 +00:00
|
|
|
'subject': self.send_get_mail_subject(cr, uid, mail, partner=partner, context=context),
|
|
|
|
'email_to': self.send_get_mail_to(cr, uid, mail, partner=partner, context=context),
|
2012-09-12 13:38:43 +00:00
|
|
|
}
|
2014-06-12 11:45:21 +00:00
|
|
|
return res
|
2012-09-12 13:38:43 +00:00
|
|
|
|
2013-05-24 11:48:57 +00:00
|
|
|
def send(self, cr, uid, ids, auto_commit=False, raise_exception=False, context=None):
|
2012-08-31 09:31:39 +00:00
|
|
|
""" Sends the selected emails immediately, ignoring their current
|
|
|
|
state (mails that have already been sent should not be passed
|
|
|
|
unless they should actually be re-sent).
|
|
|
|
Emails successfully delivered are marked as 'sent', and those
|
|
|
|
that fail to be deliver are marked as 'exception', and the
|
|
|
|
corresponding error mail is output in the server logs.
|
|
|
|
|
|
|
|
:param bool auto_commit: whether to force a commit of the mail status
|
|
|
|
after sending each mail (meant only for scheduler processing);
|
|
|
|
should never be True during normal transactions (default: False)
|
2013-05-24 11:48:57 +00:00
|
|
|
:param bool raise_exception: whether to raise an exception if the
|
2013-06-04 15:15:08 +00:00
|
|
|
email sending process has failed
|
2012-08-31 09:31:39 +00:00
|
|
|
:return: True
|
2012-08-15 17:08:22 +00:00
|
|
|
"""
|
2014-07-06 14:44:26 +00:00
|
|
|
context = dict(context or {})
|
2012-08-15 17:08:22 +00:00
|
|
|
ir_mail_server = self.pool.get('ir.mail_server')
|
2014-05-02 14:44:31 +00:00
|
|
|
ir_attachment = self.pool['ir.attachment']
|
2013-02-25 16:48:57 +00:00
|
|
|
for mail in self.browse(cr, SUPERUSER_ID, ids, context=context):
|
2012-08-15 17:08:22 +00:00
|
|
|
try:
|
2014-03-05 17:36:10 +00:00
|
|
|
# TDE note: remove me when model_id field is present on mail.message - done here to avoid doing it multiple times in the sub method
|
|
|
|
if mail.model:
|
|
|
|
model_id = self.pool['ir.model'].search(cr, SUPERUSER_ID, [('model', '=', mail.model)], context=context)[0]
|
|
|
|
model = self.pool['ir.model'].browse(cr, SUPERUSER_ID, model_id, context=context)
|
|
|
|
else:
|
|
|
|
model = None
|
|
|
|
if model:
|
|
|
|
context['model_name'] = model.name
|
2014-05-07 17:01:12 +00:00
|
|
|
|
2014-05-02 14:44:31 +00:00
|
|
|
# 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]
|
2014-05-05 12:38:52 +00:00
|
|
|
attachments = [(a['datas_fname'], base64.b64decode(a['datas']))
|
|
|
|
for a in ir_attachment.read(cr, SUPERUSER_ID, attachment_ids,
|
|
|
|
['datas_fname', 'datas'])]
|
2014-05-07 17:01:12 +00:00
|
|
|
|
2012-09-12 13:38:43 +00:00
|
|
|
# specific behavior to customize the send email for notified partners
|
2012-09-13 15:48:44 +00:00
|
|
|
email_list = []
|
2013-02-25 16:48:57 +00:00
|
|
|
if mail.email_to:
|
2012-09-13 15:48:44 +00:00
|
|
|
email_list.append(self.send_get_email_dict(cr, uid, mail, context=context))
|
2013-02-25 16:48:57 +00:00
|
|
|
for partner in mail.recipient_ids:
|
|
|
|
email_list.append(self.send_get_email_dict(cr, uid, mail, partner=partner, context=context))
|
2013-08-06 15:11:43 +00:00
|
|
|
# headers
|
|
|
|
headers = {}
|
|
|
|
bounce_alias = self.pool['ir.config_parameter'].get_param(cr, uid, "mail.bounce.alias", context=context)
|
|
|
|
catchall_domain = self.pool['ir.config_parameter'].get_param(cr, uid, "mail.catchall.domain", context=context)
|
|
|
|
if bounce_alias and catchall_domain:
|
|
|
|
if mail.model and mail.res_id:
|
|
|
|
headers['Return-Path'] = '%s-%d-%s-%d@%s' % (bounce_alias, mail.id, mail.model, mail.res_id, catchall_domain)
|
|
|
|
else:
|
|
|
|
headers['Return-Path'] = '%s-%d@%s' % (bounce_alias, mail.id, catchall_domain)
|
2014-06-20 14:34:27 +00:00
|
|
|
if mail.headers:
|
|
|
|
try:
|
|
|
|
headers.update(eval(mail.headers))
|
|
|
|
except Exception:
|
|
|
|
pass
|
2012-08-15 17:08:22 +00:00
|
|
|
|
2014-09-22 15:48:11 +00:00
|
|
|
# Writing on the mail object may fail (e.g. lock on user) which
|
|
|
|
# would trigger a rollback *after* actually sending the email.
|
|
|
|
# To avoid sending twice the same email, provoke the failure earlier
|
|
|
|
mail.write({'state': 'exception'})
|
|
|
|
mail_sent = False
|
|
|
|
|
2012-08-31 09:31:39 +00:00
|
|
|
# build an RFC2822 email.message.Message object and send it without queuing
|
2013-08-06 15:11:43 +00:00
|
|
|
res = None
|
2012-09-13 15:48:44 +00:00
|
|
|
for email in email_list:
|
2012-09-12 13:38:43 +00:00
|
|
|
msg = ir_mail_server.build_email(
|
2013-08-06 15:11:43 +00:00
|
|
|
email_from=mail.email_from,
|
|
|
|
email_to=email.get('email_to'),
|
|
|
|
subject=email.get('subject'),
|
|
|
|
body=email.get('body'),
|
|
|
|
body_alternative=email.get('body_alternative'),
|
|
|
|
email_cc=tools.email_split(mail.email_cc),
|
|
|
|
reply_to=mail.reply_to,
|
|
|
|
attachments=attachments,
|
|
|
|
message_id=mail.message_id,
|
|
|
|
references=mail.references,
|
|
|
|
object_id=mail.res_id and ('%s-%s' % (mail.res_id, mail.model)),
|
|
|
|
subtype='html',
|
|
|
|
subtype_alternative='plain',
|
2014-06-20 14:34:27 +00:00
|
|
|
headers=headers)
|
2014-10-03 13:19:30 +00:00
|
|
|
try:
|
2014-11-04 16:54:48 +00:00
|
|
|
res = ir_mail_server.send_email(cr, uid, msg,
|
2013-08-06 15:11:43 +00:00
|
|
|
mail_server_id=mail.mail_server_id.id,
|
|
|
|
context=context)
|
2014-10-03 13:19:30 +00:00
|
|
|
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
|
2012-08-15 17:08:22 +00:00
|
|
|
if res:
|
2012-09-12 12:01:44 +00:00
|
|
|
mail.write({'state': 'sent', 'message_id': res})
|
2012-12-18 02:11:23 +00:00
|
|
|
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
|
2014-07-06 14:44:26 +00:00
|
|
|
if mail_sent:
|
|
|
|
_logger.info('Mail with ID %r and Message-Id %r successfully sent', mail.id, mail.message_id)
|
2014-04-08 12:40:53 +00:00
|
|
|
self._postprocess_sent_message(cr, uid, mail, context=context, mail_sent=mail_sent)
|
2014-04-30 10:25:52 +00:00
|
|
|
except MemoryError:
|
|
|
|
# prevent catching transient MemoryErrors, bubble up to notify user or abort cron job
|
|
|
|
# instead of marking the mail as failed
|
2014-05-02 14:44:31 +00:00
|
|
|
_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)
|
2014-04-30 10:25:52 +00:00
|
|
|
raise
|
2013-06-04 15:15:08 +00:00
|
|
|
except Exception as e:
|
|
|
|
_logger.exception('failed sending mail.mail %s', mail.id)
|
|
|
|
mail.write({'state': 'exception'})
|
2014-04-08 12:40:53 +00:00
|
|
|
self._postprocess_sent_message(cr, uid, mail, context=context, mail_sent=False)
|
2013-05-24 11:48:57 +00:00
|
|
|
if raise_exception:
|
2013-06-04 15:15:08 +00:00
|
|
|
if isinstance(e, AssertionError):
|
|
|
|
# get the args of the original error, wrap into a value and throw a MailDeliveryException
|
|
|
|
# that is an except_orm, with name and value as arguments
|
|
|
|
value = '. '.join(e.args)
|
|
|
|
raise MailDeliveryException(_("Mail Delivery Failed"), value)
|
2013-05-24 11:48:57 +00:00
|
|
|
raise
|
2012-08-15 17:08:22 +00:00
|
|
|
|
2014-03-14 17:48:09 +00:00
|
|
|
if auto_commit is True:
|
2012-08-15 17:08:22 +00:00
|
|
|
cr.commit()
|
|
|
|
return True
|