Browse Source
[REF] check email_from at mail.mail, because it's more stable variant
[REF] check email_from at mail.mail, because it's more stable variant
across different versions of odoo [IMP] use new parameter for default alias: mail.catchall.alias_frompull/1/head
Ivan Yelizariev
10 years ago
4 changed files with 46 additions and 135 deletions
-
19README.rst
-
38__openerp__.py
-
10data.xml
-
112mail_fix_553.py
@ -0,0 +1,19 @@ |
|||||
|
Fix mail error 553 |
||||
|
================== |
||||
|
|
||||
|
Module updates 'FROM' field to portal@MYDOMAIN.COM value in order to fix 553 error on a mail service that checks FROM field. |
||||
|
|
||||
|
E.g: |
||||
|
|
||||
|
* Customer send email from USER@CUSTOMER.com to info@MYDOMAIN.COM |
||||
|
* odoo accept email and try to send notifcation to related odoo users. E.g to admin@gmail.com. |
||||
|
* By default odoo prepare notification email with parameters as follows: |
||||
|
|
||||
|
* FROM: user@CUSTOMER.com |
||||
|
* TO: admin@gmail.com |
||||
|
|
||||
|
if you mail service provider, e.g. pdd.yandex.ru, doesn't allow emails with a FROM value differ from ...@MYDOMAIN.COM, then you get 553. This is why you need to update FROM value to portal@MYDOMAIN.COM |
||||
|
|
||||
|
You can configure default alias at Settings -> System Parameters -> mail.catchall.alias_from |
||||
|
|
||||
|
Tested on Odoo 8.0 d023c079ed86468436f25da613bf486a4a17d625 |
@ -1,44 +1,10 @@ |
|||||
{ |
{ |
||||
"name" : "Fix error 553", |
|
||||
|
"name" : "Fix mail error 553", |
||||
"version" : "0.3", |
"version" : "0.3", |
||||
"author" : "Ivan Yelizariev", |
"author" : "Ivan Yelizariev", |
||||
"category" : "Mail", |
"category" : "Mail", |
||||
"website" : "https://yelizariev.github.io", |
"website" : "https://yelizariev.github.io", |
||||
"description": """ |
|
||||
Module uses system parameters: |
|
||||
|
|
||||
* mail.catchall.alias |
|
||||
* mail.catchall.domain |
|
||||
|
|
||||
Module updates reply-to field if it posible to sender alias |
|
||||
|
|
||||
Module updates 'FROM' field to catchall value in order to fix problem like that: |
|
||||
|
|
||||
2014-01-18 06:25:56,532 6789 INFO trunk openerp.addons.mail.mail_thread: Routing mail from <user@CUSTOMER.com> to info@MYDOMAIN.com with Message-Id <49131390026345@web16h.yandex.ru>: direct alias match: (u'res.users', 1, {}, 1, browse_record(mail.alias, 1)) |
|
||||
2014-01-18 06:25:57,212 6789 ERROR trunk openerp.addons.base.ir.ir_mail_server: Mail delivery failed via SMTP server 'smtp.yandex.ru'. |
|
||||
SMTPSenderRefused: 553 |
|
||||
5.7.1 Sender address rejected: not owned by auth user. |
|
||||
user@CUSTOMER.com |
|
||||
Traceback (most recent call last): |
|
||||
File "/mnt/files/src/openerp-server/server/openerp/addons/base/ir/ir_mail_server.py", line 465, in send_email |
|
||||
smtp.sendmail(smtp_from, smtp_to_list, message.as_string()) |
|
||||
File "/usr/lib/python2.7/smtplib.py", line 722, in sendmail |
|
||||
raise SMTPSenderRefused(code, resp, from_addr) |
|
||||
SMTPSenderRefused: (553, '5.7.1 Sender address rejected: not owned by auth user.', 'user@CUSTOMER.com') |
|
||||
|
|
||||
2014-01-18 06:25:57,216 6789 ERROR trunk openerp.addons.mail.mail_mail: failed sending mail.mail 2 |
|
||||
Traceback (most recent call last): |
|
||||
File "/mnt/files/src/openerp-server/addons/mail/mail_mail.py", line 284, in send |
|
||||
context=context) |
|
||||
File "/mnt/files/src/openerp-server/server/openerp/addons/base/ir/ir_mail_server.py", line 478, in send_email |
|
||||
raise MailDeliveryException(_("Mail Delivery Failed"), msg) |
|
||||
MailDeliveryException: (u'Mail Delivery Failed', u"Mail delivery failed via SMTP server 'smtp.yandex.ru'.\nSMTPSenderRefused: 553\n5.7.1 Sender address rejected: not owned by auth user.\nuser@CUSTOMER.com") |
|
||||
2014-01-18 06:25:57,223 6789 INFO trunk openerp.addons.fetchmail.fetchmail: fetched/processed 1 email(s) on imap server yandex |
|
||||
|
|
||||
""", |
|
||||
"depends" : ["base", "mail"], |
"depends" : ["base", "mail"], |
||||
#"init_xml" : [], |
|
||||
#"update_xml" : [], |
|
||||
#"active": True, |
|
||||
|
"data": ["data.xml"], |
||||
"installable": True |
"installable": True |
||||
} |
} |
@ -0,0 +1,10 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<openerp> |
||||
|
<data noupdate="1"> |
||||
|
<!-- Catchall Email Alias --> |
||||
|
<record id="icp_mail_catchall_alias_from" model="ir.config_parameter"> |
||||
|
<field name="key">mail.catchall.alias_from</field> |
||||
|
<field name="value">portal</field> |
||||
|
</record> |
||||
|
</data> |
||||
|
</openerp> |
@ -1,117 +1,33 @@ |
|||||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||||
|
|
||||
import base64 |
|
||||
import logging |
|
||||
import re |
import re |
||||
from urllib import urlencode |
|
||||
from urlparse import urljoin |
|
||||
|
|
||||
from openerp import tools |
|
||||
from openerp import SUPERUSER_ID |
from openerp import SUPERUSER_ID |
||||
from openerp.addons.base.ir.ir_mail_server import MailDeliveryException |
|
||||
from openerp.osv import fields, osv |
from openerp.osv import fields, osv |
||||
from openerp.tools.translate import _ |
|
||||
|
|
||||
|
import logging |
||||
_logger = logging.getLogger(__name__) |
_logger = logging.getLogger(__name__) |
||||
|
|
||||
class mail_mail(osv.Model): |
|
||||
|
class mail_mail(osv.osv): |
||||
_inherit = "mail.mail" |
_inherit = "mail.mail" |
||||
def send(self, cr, uid, ids, auto_commit=False, raise_exception=False, context=None): |
|
||||
""" 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) |
|
||||
:param bool raise_exception: whether to raise an exception if the |
|
||||
email sending process has failed |
|
||||
:return: True |
|
||||
""" |
|
||||
catchall_alias = self.pool['ir.config_parameter'].get_param(cr, uid, "mail.catchall.alias", context=context) |
|
||||
|
def _fix_email_from(cr, uid, email_from): |
||||
|
catchall_alias = self.pool['ir.config_parameter'].get_param(cr, uid, "mail.catchall.alias_from", context=context) |
||||
catchall_domain = self.pool['ir.config_parameter'].get_param(cr, uid, "mail.catchall.domain", context=context) |
catchall_domain = self.pool['ir.config_parameter'].get_param(cr, uid, "mail.catchall.domain", context=context) |
||||
|
|
||||
correct_email_from = '@%s>?\s*$'%catchall_domain |
correct_email_from = '@%s>?\s*$'%catchall_domain |
||||
default_email_from = '%s@%s' % (catchall_alias, catchall_domain) |
default_email_from = '%s@%s' % (catchall_alias, catchall_domain) |
||||
|
|
||||
ir_mail_server = self.pool.get('ir.mail_server') |
|
||||
|
|
||||
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))) |
|
||||
# specific behavior to customize the send email for notified partners |
|
||||
email_list = [] |
|
||||
if mail.email_to: |
|
||||
email_list.append(self.send_get_email_dict(cr, uid, mail, context=context)) |
|
||||
for partner in mail.recipient_ids: |
|
||||
email_list.append(self.send_get_email_dict(cr, uid, mail, partner=partner, context=context)) |
|
||||
# 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) |
|
||||
|
|
||||
# build an RFC2822 email.message.Message object and send it without queuing |
|
||||
res = None |
|
||||
for email in email_list: |
|
||||
email_from = mail.email_from |
|
||||
reply_to = mail.reply_to |
|
||||
if re.search(correct_email_from, email_from) is None: |
|
||||
|
if not email_from or re.search(correct_email_from, email_from) is None: |
||||
email_from = default_email_from |
email_from = default_email_from |
||||
else: |
|
||||
reply_to = email_from |
|
||||
|
return email_from |
||||
|
|
||||
msg = ir_mail_server.build_email( |
|
||||
email_from=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=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', |
|
||||
headers=headers) |
|
||||
res = ir_mail_server.send_email(cr, uid, msg, |
|
||||
mail_server_id=mail.mail_server_id.id, |
|
||||
context=context) |
|
||||
|
def create(self, cr, uid, values, context=None): |
||||
|
if 'email_from' in values: |
||||
|
values['email_from'] = self._fix_email_from(cr, uid, values['email_from']) |
||||
|
|
||||
if res: |
|
||||
mail.write({'state': 'sent', 'message_id': res}) |
|
||||
mail_sent = True |
|
||||
else: |
|
||||
mail.write({'state': 'exception'}) |
|
||||
mail_sent = False |
|
||||
|
return super(mail_mail, self).create(cr, uid, values, context=context) |
||||
|
|
||||
# /!\ 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: |
|
||||
self._postprocess_sent_message(cr, uid, mail, context=context) |
|
||||
except Exception as e: |
|
||||
_logger.exception('failed sending mail.mail %s', mail.id) |
|
||||
mail.write({'state': 'exception'}) |
|
||||
if raise_exception: |
|
||||
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) |
|
||||
raise |
|
||||
|
def write(self, cr, uid, ids, values, context=None): |
||||
|
if 'email_from' in values: |
||||
|
values['email_from'] = self._fix_email_from(cr, uid, values['email_from']) |
||||
|
|
||||
if auto_commit == True: |
|
||||
cr.commit() |
|
||||
return True |
|
||||
|
return super(mail_mail, self).write(cr, uid, ids, values, context=context) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue