credativ team mailing list archive
-
credativ team
-
Mailing list archive
-
Message #06152
[Branch ~credativ/openobject-addons/6.1] Rev 7079: [FIX] Lock obtained on mail_message before sending e-mail
------------------------------------------------------------
revno: 7079
committer: Tom Pickering <tom.pickering@xxxxxxxxxxxxxx>
branch nick: 6.1
timestamp: Wed 2016-09-07 10:13:19 +0100
message:
[FIX] Lock obtained on mail_message before sending e-mail
modified:
mail/mail_message.py
--
lp:~credativ/openobject-addons/6.1
https://code.launchpad.net/~credativ/openobject-addons/6.1
Your team credativ is subscribed to branch lp:~credativ/openobject-addons/6.1.
To unsubscribe from this branch go to https://code.launchpad.net/~credativ/openobject-addons/6.1/+edit-subscription
=== modified file 'mail/mail_message.py'
--- mail/mail_message.py 2015-02-03 13:54:34 +0000
+++ mail/mail_message.py 2016-09-07 09:13:19 +0000
@@ -24,18 +24,23 @@
import datetime
import dateutil.parser
import email
+import pooler
import logging
import pytz
import re
import time
from email.header import decode_header
from email.message import Message
+from contextlib import closing
import tools
from osv import osv
from osv import fields
from tools.translate import _
from openerp import SUPERUSER_ID
+
+from psycopg2 import OperationalError
+
try:
from openerp.addons.base.ir.ir_mail_server import MailTransientDeliveryException
except:
@@ -505,63 +510,72 @@
if context is None:
context = {}
ir_mail_server = self.pool.get('ir.mail_server')
- self.write(cr, uid, ids, {'state': 'outgoing'}, context=context)
- for message in self.browse(cr, uid, ids, context=context):
- try:
- attachments = []
- for attach in message.attachment_ids:
- attachments.append((attach.datas_fname, base64.b64decode(attach.datas)))
-
- body = message.body_html if message.subtype == 'html' else message.body_text
- body_alternative = None
- subtype_alternative = None
- if message.subtype == 'html' and message.body_text:
- # we have a plain text alternative prepared, pass it to
- # build_message instead of letting it build one
- body_alternative = message.body_text
- subtype_alternative = 'plain'
-
- msg = ir_mail_server.build_email(
- email_from=message.email_from,
- email_to=to_email(message.email_to),
- subject=message.subject,
- body=body,
- body_alternative=body_alternative,
- email_cc=to_email(message.email_cc),
- email_bcc=to_email(message.email_bcc),
- reply_to=message.reply_to,
- attachments=attachments, message_id=message.message_id,
- references = message.references,
- object_id=message.res_id and ('%s-%s' % (message.res_id,message.model)),
- subtype=message.subtype,
- subtype_alternative=subtype_alternative,
- headers=message.headers and ast.literal_eval(message.headers))
- res = ir_mail_server.send_email(cr, uid, msg,
- mail_server_id=message.mail_server_id.id,
- context=context)
- if res:
- message.write({'state':'sent', 'message_id': res})
- message_sent = True
- else:
+ for msg_id in ids:
+ with closing(pooler.get_db(cr.dbname).cursor()) as _cr:
+ try:
+ _cr.execute('SELECT * FROM mail_message WHERE id = %s FOR UPDATE NOWAIT', [msg_id])
+ message = self.browse(_cr, uid, msg_id, context=context)
+ self.write(_cr, uid, msg_id, {'state': 'outgoing'}, context=context)
+
+ attachments = []
+ for attach in message.attachment_ids:
+ attachments.append((attach.datas_fname, base64.b64decode(attach.datas)))
+
+ body = message.body_html if message.subtype == 'html' else message.body_text
+ body_alternative = None
+ subtype_alternative = None
+ if message.subtype == 'html' and message.body_text:
+ # we have a plain text alternative prepared, pass it to
+ # build_message instead of letting it build one
+ body_alternative = message.body_text
+ subtype_alternative = 'plain'
+
+ msg = ir_mail_server.build_email(
+ email_from=message.email_from,
+ email_to=to_email(message.email_to),
+ subject=message.subject,
+ body=body,
+ body_alternative=body_alternative,
+ email_cc=to_email(message.email_cc),
+ email_bcc=to_email(message.email_bcc),
+ reply_to=message.reply_to,
+ attachments=attachments, message_id=message.message_id,
+ references = message.references,
+ object_id=message.res_id and ('%s-%s' % (message.res_id,message.model)),
+ subtype=message.subtype,
+ subtype_alternative=subtype_alternative,
+ headers=message.headers and ast.literal_eval(message.headers))
+ res = ir_mail_server.send_email(_cr, uid, msg,
+ mail_server_id=message.mail_server_id.id,
+ context=context)
+ if res:
+ message.write({'state':'sent', 'message_id': res})
+ message_sent = True
+ else:
+ message.write({'state':'exception'})
+ message_sent = False
+
+ # if auto_delete=True then delete that sent messages as well as attachments
+ if message_sent and message.auto_delete:
+ self.pool.get('ir.attachment').unlink(_cr, uid,
+ [x.id for x in message.attachment_ids \
+ if x.res_model == self._name and \
+ x.res_id == message.id],
+ context=context)
+ message.unlink()
+
+ _cr.commit()
+ except MailTransientDeliveryException:
+ pass
+ except OperationalError:
+ _logger.exception('failed sending mail.message %s and unable to update state', msg_id)
+ # We can't use this cursor any more - attempting to updating
+ # the message state will just throw a new exception.
+ except Exception:
+ _logger.exception('failed sending mail.message %s', msg_id)
message.write({'state':'exception'})
- message_sent = False
-
- # if auto_delete=True then delete that sent messages as well as attachments
- if message_sent and message.auto_delete:
- self.pool.get('ir.attachment').unlink(cr, uid,
- [x.id for x in message.attachment_ids \
- if x.res_model == self._name and \
- x.res_id == message.id],
- context=context)
- message.unlink()
- except MailTransientDeliveryException:
- pass
- except Exception:
- _logger.exception('failed sending mail.message %s', message.id)
- message.write({'state':'exception'})
-
- if auto_commit == True:
- cr.commit()
+ _cr.commit()
+
return True
def cancel(self, cr, uid, ids, context=None):