From 19e532e44b09069df36d8f6620a08d589485bbde Mon Sep 17 00:00:00 2001 From: Dave Lasley Date: Fri, 24 May 2019 12:42:58 +0200 Subject: [PATCH 01/51] ADD mail_outbound_static: Allow configuration of from email header * Allow for the configuration of the FROM header for outbound emails, and move the existing from header to Sender as per RFC-2822 --- mail_outbound_static/README.rst | 62 ++++++++++++++++ mail_outbound_static/__init__.py | 5 ++ mail_outbound_static/__manifest__.py | 21 ++++++ mail_outbound_static/models/__init__.py | 5 ++ mail_outbound_static/models/ir_mail_server.py | 50 +++++++++++++ .../static/description/icon.png | Bin 0 -> 9455 bytes mail_outbound_static/tests/__init__.py | 5 ++ mail_outbound_static/tests/test.msg | 70 ++++++++++++++++++ .../tests/test_ir_mail_server.py | 70 ++++++++++++++++++ .../views/ir_mail_server_view.xml | 21 ++++++ 10 files changed, 309 insertions(+) create mode 100644 mail_outbound_static/README.rst create mode 100644 mail_outbound_static/__init__.py create mode 100644 mail_outbound_static/__manifest__.py create mode 100644 mail_outbound_static/models/__init__.py create mode 100644 mail_outbound_static/models/ir_mail_server.py create mode 100644 mail_outbound_static/static/description/icon.png create mode 100644 mail_outbound_static/tests/__init__.py create mode 100644 mail_outbound_static/tests/test.msg create mode 100644 mail_outbound_static/tests/test_ir_mail_server.py create mode 100644 mail_outbound_static/views/ir_mail_server_view.xml diff --git a/mail_outbound_static/README.rst b/mail_outbound_static/README.rst new file mode 100644 index 000000000..9918b8605 --- /dev/null +++ b/mail_outbound_static/README.rst @@ -0,0 +1,62 @@ +.. image:: https://img.shields.io/badge/license-LGPL--3-blue.svg + :target: http://www.gnu.org/licenses/lgpl.html + :alt: License: LGPL-3 + +==================== +Mail Outbound Static +==================== + +This module brings Odoo outbound emails in to strict compliance with RFC-2822 +by allowing for a statically configured From header, with the sender's e-mail +being appended into the proper Sender header instead. + +Usage +===== + +* Navigate to an Outbound Email Server +* Set the `Email From` option to an email address + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/205/10.0 + +Road Map +======== + +* Allow for domain-based whitelist that will not be manipulated + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smash it by providing detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Dave Lasley + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/mail_outbound_static/__init__.py b/mail_outbound_static/__init__.py new file mode 100644 index 000000000..fd02263ce --- /dev/null +++ b/mail_outbound_static/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from . import models diff --git a/mail_outbound_static/__manifest__.py b/mail_outbound_static/__manifest__.py new file mode 100644 index 000000000..be9eaadef --- /dev/null +++ b/mail_outbound_static/__manifest__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Copyright 2016-2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +{ + 'name': 'Mail Outbound Static', + 'summary': 'Allows you to configure the from header for a mail server.', + 'version': '10.0.1.0.1', + 'category': 'Discuss', + 'website': 'https://laslabs.com/', + 'author': 'LasLabs, Odoo Community Association (OCA)', + 'license': 'LGPL-3', + 'application': False, + 'installable': True, + 'depends': [ + 'base', + ], + 'data': [ + 'views/ir_mail_server_view.xml', + ], +} diff --git a/mail_outbound_static/models/__init__.py b/mail_outbound_static/models/__init__.py new file mode 100644 index 000000000..e8eda250c --- /dev/null +++ b/mail_outbound_static/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from . import ir_mail_server diff --git a/mail_outbound_static/models/ir_mail_server.py b/mail_outbound_static/models/ir_mail_server.py new file mode 100644 index 000000000..78b6d6ba4 --- /dev/null +++ b/mail_outbound_static/models/ir_mail_server.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from odoo import api, fields, models + + +class IrMailServer(models.Model): + + _inherit = 'ir.mail_server' + + smtp_from = fields.Char( + string='Email From', + help='Set this in order to email from a specific address.' + ) + + @api.model + def send_email(self, message, mail_server_id=None, smtp_server=None, + *args, **kwargs): + + # Replicate logic from core to get mail server + mail_server = None + if mail_server_id: + mail_server = self.sudo().browse(mail_server_id) + elif not smtp_server: + mail_server = self.sudo().search([], order='sequence', limit=1) + + if mail_server and mail_server.smtp_from: + split_from = message['From'].rsplit(' <', 1) + if len(split_from) > 1: + email_from = '%s <%s>' % ( + split_from[0], mail_server.smtp_from, + ) + else: + email_from = mail_server.smtp_from + + message.replace_header('From', email_from) + bounce_alias = self.env['ir.config_parameter'].get_param( + "mail.bounce.alias") + if not bounce_alias: + # then, bounce handling is disabled and we want + # Return-Path = From + if message.has_key('Return-Path'): + message.replace_header('Return-Path', email_from) + else: + message.add_header('Return-Path', email_from) + + return super(IrMailServer, self).send_email( + message, mail_server_id, smtp_server, *args, **kwargs + ) diff --git a/mail_outbound_static/static/description/icon.png b/mail_outbound_static/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z z?n?eq1XP>p-IM$Z^C;2L3itnbJZAip*Zo0aw2bs8@(s^~*8T9go!%dHcAz2lM;`yp zD=7&xjFV$S&5uDaiScyD?B-i1ze`+CoRtz`Wn+Zl&#s4&}MO{@N!ufrzjG$B79)Y2d3tBk&)TxUTw@QS0TEL_?njX|@vq?Uz(nBFK5Pq7*xj#u*R&i|?7+6# z+|r_n#SW&LXhtheZdah{ZVoqwyT{D>MC3nkFF#N)xLi{p7J1jXlmVeb;cP5?e(=f# zuT7fvjSbjS781v?7{)-X3*?>tq?)Yd)~|1{BDS(pqC zC}~H#WXlkUW*H5CDOo<)#x7%RY)A;ShGhI5s*#cRDA8YgqG(HeKDx+#(ZQ?386dv! zlXCO)w91~Vw4AmOcATuV653fa9R$fyK8ul%rG z-wfS zihugoZyr38Im?Zuh6@RcF~t1anQu7>#lPpb#}4cOA!EM11`%f*07RqOVkmX{p~KJ9 z^zP;K#|)$`^Rb{rnHGH{~>1(fawV0*Z#)}M`m8-?ZJV<+e}s9wE# z)l&az?w^5{)`S(%MRzxdNqrs1n*-=jS^_jqE*5XDrA0+VE`5^*p3CuM<&dZEeCjoz zR;uu_H9ZPZV|fQq`Cyw4nscrVwi!fE6ciMmX$!_hN7uF;jjKG)d2@aC4ropY)8etW=xJvni)8eHi`H$%#zn^WJ5NLc-rqk|u&&4Z6fD_m&JfSI1Bvb?b<*n&sfl0^t z=HnmRl`XrFvMKB%9}>PaA`m-fK6a0(8=qPkWS5bb4=v?XcWi&hRY?O5HdulRi4?fN zlsJ*N-0Qw+Yic@s0(2uy%F@ib;GjXt01Fmx5XbRo6+n|pP(&nodMoap^z{~q ziEeaUT@Mxe3vJSfI6?uLND(CNr=#^W<1b}jzW58bIfyWTDle$mmS(|x-0|2UlX+9k zQ^EX7Nw}?EzVoBfT(-LT|=9N@^hcn-_p&sqG z&*oVs2JSU+N4ZD`FhCAWaS;>|wH2G*Id|?pa#@>tyxX`+4HyIArWDvVrX)2WAOQff z0qyHu&-S@i^MS-+j--!pr4fPBj~_8({~e1bfcl0wI1kaoN>mJL6KUPQm5N7lB(ui1 zE-o%kq)&djzWJ}ob<-GfDlkB;F31j-VHKvQUGQ3sp`CwyGJk_i!y^sD0fqC@$9|jO zOqN!r!8-p==F@ZVP=U$qSpY(gQ0)59P1&t@y?5rvg<}E+GB}26NYPp4f2YFQrQtot5mn3wu_qprZ=>Ig-$ zbW26Ws~IgY>}^5w`vTB(G`PTZaDiGBo5o(tp)qli|NeV( z@H_=R8V39rt5J5YB2Ky?4eJJ#b`_iBe2ot~6%7mLt5t8Vwi^Jy7|jWXqa3amOIoRb zOr}WVFP--DsS`1WpN%~)t3R!arKF^Q$e12KEqU36AWwnCBICpH4XCsfnyrHr>$I$4 z!DpKX$OKLWarN7nv@!uIA+~RNO)l$$w}p(;b>mx8pwYvu;dD_unryX_NhT8*Tj>BTrTTL&!?O+%Rv;b?B??gSzdp?6Uug9{ zd@V08Z$BdI?fpoCS$)t4mg4rT8Q_I}h`0d-vYZ^|dOB*Q^S|xqTV*vIg?@fVFSmMpaw0qtTRbx} z({Pg?#{2`sc9)M5N$*N|4;^t$+QP?#mov zGVC@I*lBVrOU-%2y!7%)fAKjpEFsgQc4{amtiHb95KQEwvf<(3T<9-Zm$xIew#P22 zc2Ix|App^>v6(3L_MCU0d3W##AB0M~3D00EWoKZqsJYT(#@w$Y_H7G22M~ApVFTRHMI_3be)Lkn#0F*V8Pq zc}`Cjy$bE;FJ6H7p=0y#R>`}-m4(0F>%@P|?7fx{=R^uFdISRnZ2W_xQhD{YuR3t< z{6yxu=4~JkeA;|(J6_nv#>Nvs&FuLA&PW^he@t(UwFFE8)|a!R{`E`K`i^ZnyE4$k z;(749Ix|oi$c3QbEJ3b~D_kQsPz~fIUKym($a_7dJ?o+40*OLl^{=&oq$<#Q(yyrp z{J-FAniyAw9tPbe&IhQ|a`DqFTVQGQ&Gq3!C2==4x{6EJwiPZ8zub-iXoUtkJiG{} zPaR&}_fn8_z~(=;5lD-aPWD3z8PZS@AaUiomF!G8I}Mf>e~0g#BelA-5#`cj;O5>N Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/mail_outbound_static/tests/__init__.py b/mail_outbound_static/tests/__init__.py new file mode 100644 index 000000000..b5038cdfa --- /dev/null +++ b/mail_outbound_static/tests/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from . import test_ir_mail_server diff --git a/mail_outbound_static/tests/test.msg b/mail_outbound_static/tests/test.msg new file mode 100644 index 000000000..1f0b96da3 --- /dev/null +++ b/mail_outbound_static/tests/test.msg @@ -0,0 +1,70 @@ +Delivered-To: test@gmail.com +Received: by 10.74.138.167 with SMTP id m36csp7226976ooj; + Tue, 12 Sep 2017 10:37:56 -0700 (PDT) +X-Google-Smtp-Source: AOwi7QDKSb3BE6lIhVXub9wcPA/HxFKKpnNPconNr9f1L35SVw+EIm8itVQkbOdAW6TohImypmrF +X-Received: by 10.28.158.208 with SMTP id h199mr250060wme.47.1505237876258; + Tue, 12 Sep 2017 10:37:56 -0700 (PDT) +ARC-Seal: i=1; a=rsa-sha256; t=1505237876; cv=none; + d=google.com; s=arc-20160816; + b=E2B6KUxHOJQk1YrT12BpitEMCgkxyqEXcFlwPWKjA/i/Xyvlh+09spNOF4VPmD/ZJm + 5lkY6hYyxvIH2RpRPeZVPkRIYhaEASkMIygdJu9Gd4weBdO2rd8iP/zSGHYyAmO/hLN2 + 64hXtKexrWnO/YNWlpfhAo1kiwgSRVnZx55EopbWP49cy7BzKfwr1kHN0T9A5Lw1w+BW + ZrXdCX6LRxHS2USKHb76PAVt0bhwsM/ZznBauR2zNKYcPxAWzdpN/vK3BDmWUdqbbSaB + BOKINjuI9EmWynogDZE7Riu+sbc5QafE3owla1/2d0Bogp9FLtJe0YyQeW2qLvZKcmlI + ftSQ== +ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; + h=to:list-archive:list-unsubscribe:list-subscribe:precedence + :list-post:list-id:date:reply-to:from:subject:references:message-id + :mime-version:arc-authentication-results; + bh=DwvSiw5K7ryb4S8O/8HcIaGhJqbOxcXKsnPAr63iQZ4=; + b=U0Ac9Rqvv+tfqO9fCx+F79oZknn3rOv9N9ekViEuL5DtjpJxKDDkO1xw//sV3eRILT + nqGuxd2yQXwC4U+WAwraBwoLC3ScHb/9gWtzlrLCgv6WbNE7HZi5g6L8c0LWRN24cIe9 + AOdc/8fOdGoaL8yajrGEHgMz9B2KMltA9tZyxFOeKsyODxJ6iWjXcG1BSQTxERwosV3h + ch8AznQr7xLLvc/u9VTEqC5ome3RqsxKRxOGenEqIbCOr11sxwpZQdQcNR6faNRom3+2 + 6gz++4tVIV9cqYX1j9eEU/ufoUzBJ6Uzm0jMGZZQOHAF+YX3tZUEsPmc75PsvRCAIWby + urMg== +ARC-Authentication-Results: i=1; mx.google.com; + spf=pass (google.com: domain of postmaster-odoo@odoo-community.org designates 2a01:4f8:a0:430d::2 as permitted sender) smtp.mailfrom=postmaster-odoo@odoo-community.org; + dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=QUARANTINE) header.from=laslabs.com +Return-Path: +Received: from odoo-community.org (odoo-community.org. [2a01:4f8:a0:430d::2]) + by mx.google.com with ESMTP id j72si1795626wmg.60.2017.09.12.10.37.55 + for ; + Tue, 12 Sep 2017 10:37:56 -0700 (PDT) +Received-SPF: pass (google.com: domain of postmaster-odoo@odoo-community.org designates 2a01:4f8:a0:430d::2 as permitted sender) client-ip=2a01:4f8:a0:430d::2; +Authentication-Results: mx.google.com; + spf=pass (google.com: domain of postmaster-odoo@odoo-community.org designates 2a01:4f8:a0:430d::2 as permitted sender) smtp.mailfrom=postmaster-odoo@odoo-community.org; + dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=QUARANTINE) header.from=laslabs.com +Received: from odoo.odoo-community.org (localhost.localdomain [127.0.0.1]) + by odoo-community.org (Postfix) with ESMTP id DB5DC2EC2277; + Tue, 12 Sep 2017 19:37:53 +0200 (CEST) +Content-Type: multipart/mixed; boundary="===============7439524030966430607==" +MIME-Version: 1.0 +Message-Id: +references: <0db43737-b846-4890-6801-44ff9617e3b3@camptocamp.com> +Subject: Re: OCA Code sprint: sprint topics +From: Dave Lasley +Reply-To: "Odoo Community Association \(OCA\) Contributors" + +Date: Tue, 12 Sep 2017 17:37:53 -0000 +List-Id: contributors.odoo-community.org +List-Post: +Precedence: list +X-Auto-Response-Suppress: OOF +List-Subscribe: +List-Unsubscribe: +List-Archive: +To: "Contributors" + +--===============7439524030966430607== +Content-Type: multipart/alternative; + boundary="===============8317593469411551167==" +MIME-Version: 1.0 + +--===============8317593469411551167== +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 + +VGhpcyBpcyBhIGZha2UsIHRlc3QgbWVzc2FnZQ== +--===============7439524030966430607==-- diff --git a/mail_outbound_static/tests/test_ir_mail_server.py b/mail_outbound_static/tests/test_ir_mail_server.py new file mode 100644 index 000000000..50e095d79 --- /dev/null +++ b/mail_outbound_static/tests/test_ir_mail_server.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 LasLabs Inc. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +import os +import threading + +from mock import MagicMock +from email import message_from_string + +from odoo.tests.common import TransactionCase + + +class TestIrMailServer(TransactionCase): + + def setUp(self): + super(TestIrMailServer, self).setUp() + self.email_from = 'derp@example.com' + self.email_from_another = 'another@example.com' + self.Model = self.env['ir.mail_server'] + self.Model.search([]).write({'smtp_from': self.email_from}) + message_file = os.path.join( + os.path.dirname(os.path.realpath(__file__)), 'test.msg', + ) + with open(message_file, 'r') as fh: + self.message = message_from_string(fh.read()) + + def _send_mail(self, message=None, mail_server_id=None, smtp_server=None): + if message is None: + message = self.message + connect = MagicMock() + thread = threading.currentThread() + setattr(thread, 'testing', False) + try: + self.Model._patch_method('connect', connect) + try: + self.Model.send_email(message, mail_server_id, smtp_server) + finally: + self.Model._revert_method('connect') + finally: + setattr(thread, 'testing', True) + send_from, send_to, message_string = connect().sendmail.call_args[0] + return message_from_string(message_string) + + def test_send_email_injects_from_no_canonical(self): + """It should inject the FROM header correctly when no canonical name. + """ + self.message.replace_header('From', 'test@example.com') + message = self._send_mail() + self.assertEqual(message['From'], self.email_from) + + def test_send_email_injects_from_with_canonical(self): + """It should inject the FROM header correctly with a canonical name. + + Note that there is an extra `<` in the canonical name to test for + proper handling in the split. + """ + user = 'Test < User' + self.message.replace_header('From', '%s ' % user) + message = self._send_mail() + self.assertEqual( + message['From'], + '%s <%s>' % (user, self.email_from), + ) + + def test_send_email_injects_sender(self): + """It should inject the Sender header into the email.""" + original_from = self.message['From'] + message = self._send_mail() + self.assertEqual(message['Sender'], original_from) diff --git a/mail_outbound_static/views/ir_mail_server_view.xml b/mail_outbound_static/views/ir_mail_server_view.xml new file mode 100644 index 000000000..b74d4aa8f --- /dev/null +++ b/mail_outbound_static/views/ir_mail_server_view.xml @@ -0,0 +1,21 @@ + + + + + + + + IR Mail Server - From Address + ir.mail_server + + + + + + + + + From fa189211ca64960e8af348c9004e01bb2fb0876b Mon Sep 17 00:00:00 2001 From: eLBati Date: Fri, 24 May 2019 14:40:45 +0200 Subject: [PATCH 02/51] Port mail_outbound_static to 12.0 Fixing and extending tests Add setup --- mail_outbound_static/README.rst | 71 ++- mail_outbound_static/__init__.py | 1 - mail_outbound_static/__manifest__.py | 3 +- mail_outbound_static/models/__init__.py | 1 - mail_outbound_static/models/ir_mail_server.py | 3 +- mail_outbound_static/readme/CONTRIBUTORS.rst | 2 + mail_outbound_static/readme/DESCRIPTION.rst | 3 + mail_outbound_static/readme/ROADMAP.rst | 1 + mail_outbound_static/readme/USAGE.rst | 2 + .../static/description/index.html | 437 ++++++++++++++++++ mail_outbound_static/tests/__init__.py | 1 - .../tests/test_ir_mail_server.py | 28 +- 12 files changed, 514 insertions(+), 39 deletions(-) create mode 100644 mail_outbound_static/readme/CONTRIBUTORS.rst create mode 100644 mail_outbound_static/readme/DESCRIPTION.rst create mode 100644 mail_outbound_static/readme/ROADMAP.rst create mode 100644 mail_outbound_static/readme/USAGE.rst create mode 100644 mail_outbound_static/static/description/index.html diff --git a/mail_outbound_static/README.rst b/mail_outbound_static/README.rst index 9918b8605..deaeba1ee 100644 --- a/mail_outbound_static/README.rst +++ b/mail_outbound_static/README.rst @@ -1,62 +1,87 @@ -.. image:: https://img.shields.io/badge/license-LGPL--3-blue.svg - :target: http://www.gnu.org/licenses/lgpl.html - :alt: License: LGPL-3 - ==================== Mail Outbound Static ==================== +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github + :target: https://github.com/OCA/social/tree/12.0/mail_outbound_static + :alt: OCA/social +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/social-12-0/social-12-0-mail_outbound_static + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/205/12.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + This module brings Odoo outbound emails in to strict compliance with RFC-2822 by allowing for a statically configured From header, with the sender's e-mail being appended into the proper Sender header instead. +**Table of contents** + +.. contents:: + :local: + Usage ===== * Navigate to an Outbound Email Server * Set the `Email From` option to an email address -.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas - :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/205/10.0 - -Road Map -======== +Known issues / Roadmap +====================== * Allow for domain-based whitelist that will not be manipulated Bug Tracker =========== -Bugs are tracked on `GitHub Issues -`_. In case of trouble, please -check there if your issue has already been reported. If you spotted it first, -help us smash it by providing detailed and welcomed feedback. +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. Credits ======= -Images ------- +Authors +~~~~~~~ -* Odoo Community Association: `Icon `_. +* LasLabs Contributors ------------- +~~~~~~~~~~~~ * Dave Lasley +* Lorenzo Battistini -Maintainer ----------- +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. .. image:: https://odoo-community.org/logo.png :alt: Odoo Community Association :target: https://odoo-community.org -This module is maintained by the OCA. - OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -To contribute to this module, please visit https://odoo-community.org. +This module is part of the `OCA/social `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/mail_outbound_static/__init__.py b/mail_outbound_static/__init__.py index fd02263ce..0639de1b6 100644 --- a/mail_outbound_static/__init__.py +++ b/mail_outbound_static/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). diff --git a/mail_outbound_static/__manifest__.py b/mail_outbound_static/__manifest__.py index be9eaadef..abdeb61a0 100644 --- a/mail_outbound_static/__manifest__.py +++ b/mail_outbound_static/__manifest__.py @@ -1,11 +1,10 @@ -# -*- coding: utf-8 -*- # Copyright 2016-2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). { 'name': 'Mail Outbound Static', 'summary': 'Allows you to configure the from header for a mail server.', - 'version': '10.0.1.0.1', + 'version': '12.0.1.0.0', 'category': 'Discuss', 'website': 'https://laslabs.com/', 'author': 'LasLabs, Odoo Community Association (OCA)', diff --git a/mail_outbound_static/models/__init__.py b/mail_outbound_static/models/__init__.py index e8eda250c..fbf8a561b 100644 --- a/mail_outbound_static/models/__init__.py +++ b/mail_outbound_static/models/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). diff --git a/mail_outbound_static/models/ir_mail_server.py b/mail_outbound_static/models/ir_mail_server.py index 78b6d6ba4..e002b4658 100644 --- a/mail_outbound_static/models/ir_mail_server.py +++ b/mail_outbound_static/models/ir_mail_server.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). @@ -40,7 +39,7 @@ def send_email(self, message, mail_server_id=None, smtp_server=None, if not bounce_alias: # then, bounce handling is disabled and we want # Return-Path = From - if message.has_key('Return-Path'): + if 'Return-Path' in message: message.replace_header('Return-Path', email_from) else: message.add_header('Return-Path', email_from) diff --git a/mail_outbound_static/readme/CONTRIBUTORS.rst b/mail_outbound_static/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..3b4618c21 --- /dev/null +++ b/mail_outbound_static/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Dave Lasley +* Lorenzo Battistini diff --git a/mail_outbound_static/readme/DESCRIPTION.rst b/mail_outbound_static/readme/DESCRIPTION.rst new file mode 100644 index 000000000..b49deb9c3 --- /dev/null +++ b/mail_outbound_static/readme/DESCRIPTION.rst @@ -0,0 +1,3 @@ +This module brings Odoo outbound emails in to strict compliance with RFC-2822 +by allowing for a statically configured From header, with the sender's e-mail +being appended into the proper Sender header instead. diff --git a/mail_outbound_static/readme/ROADMAP.rst b/mail_outbound_static/readme/ROADMAP.rst new file mode 100644 index 000000000..9cc754794 --- /dev/null +++ b/mail_outbound_static/readme/ROADMAP.rst @@ -0,0 +1 @@ +* Allow for domain-based whitelist that will not be manipulated diff --git a/mail_outbound_static/readme/USAGE.rst b/mail_outbound_static/readme/USAGE.rst new file mode 100644 index 000000000..e0283cf97 --- /dev/null +++ b/mail_outbound_static/readme/USAGE.rst @@ -0,0 +1,2 @@ +* Navigate to an Outbound Email Server +* Set the `Email From` option to an email address diff --git a/mail_outbound_static/static/description/index.html b/mail_outbound_static/static/description/index.html new file mode 100644 index 000000000..3ac7728dc --- /dev/null +++ b/mail_outbound_static/static/description/index.html @@ -0,0 +1,437 @@ + + + + + + +Mail Outbound Static + + + +
+

Mail Outbound Static

+ + +

Beta License: LGPL-3 OCA/social Translate me on Weblate Try me on Runbot

+

This module brings Odoo outbound emails in to strict compliance with RFC-2822 +by allowing for a statically configured From header, with the sender’s e-mail +being appended into the proper Sender header instead.

+

Table of contents

+ +
+

Usage

+
    +
  • Navigate to an Outbound Email Server
  • +
  • Set the Email From option to an email address
  • +
+
+
+

Known issues / Roadmap

+
    +
  • Allow for domain-based whitelist that will not be manipulated
  • +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • LasLabs
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/social project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/mail_outbound_static/tests/__init__.py b/mail_outbound_static/tests/__init__.py index b5038cdfa..8b601d0ba 100644 --- a/mail_outbound_static/tests/__init__.py +++ b/mail_outbound_static/tests/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). diff --git a/mail_outbound_static/tests/test_ir_mail_server.py b/mail_outbound_static/tests/test_ir_mail_server.py index 50e095d79..c0e1e25d3 100644 --- a/mail_outbound_static/tests/test_ir_mail_server.py +++ b/mail_outbound_static/tests/test_ir_mail_server.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). @@ -18,7 +17,12 @@ def setUp(self): self.email_from = 'derp@example.com' self.email_from_another = 'another@example.com' self.Model = self.env['ir.mail_server'] - self.Model.search([]).write({'smtp_from': self.email_from}) + self.parameter_model = self.env['ir.config_parameter'] + self.Model.create({ + 'name': 'localhost', + 'smtp_host': 'localhost', + 'smtp_from': self.email_from, + }) message_file = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'test.msg', ) @@ -57,14 +61,20 @@ def test_send_email_injects_from_with_canonical(self): """ user = 'Test < User' self.message.replace_header('From', '%s ' % user) - message = self._send_mail() + bounce_parameter = self.parameter_model.search([ + ('key', '=', 'mail.bounce.alias')]) + if bounce_parameter: + # Remove mail.bounce.alias to test Return-Path + bounce_parameter.unlink() + # Also check passing mail_server_id + mail_server_id = self.Model.sudo().search( + [], order='sequence', limit=1)[0].id + message = self._send_mail(mail_server_id=mail_server_id) self.assertEqual( message['From'], '%s <%s>' % (user, self.email_from), ) - - def test_send_email_injects_sender(self): - """It should inject the Sender header into the email.""" - original_from = self.message['From'] - message = self._send_mail() - self.assertEqual(message['Sender'], original_from) + self.assertEqual( + message['Return-Path'], + '%s <%s>' % (user, self.email_from), + ) From ef406d539f6eb917cc859f60f98a797dd320d669 Mon Sep 17 00:00:00 2001 From: Lorenzo Battistini Date: Wed, 11 Sep 2019 07:56:10 +0200 Subject: [PATCH 03/51] Update website in mail_outbound_static/__manifest__.py Co-Authored-By: Jairo Llopis --- mail_outbound_static/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mail_outbound_static/__manifest__.py b/mail_outbound_static/__manifest__.py index abdeb61a0..bb52e1e2f 100644 --- a/mail_outbound_static/__manifest__.py +++ b/mail_outbound_static/__manifest__.py @@ -6,7 +6,7 @@ 'summary': 'Allows you to configure the from header for a mail server.', 'version': '12.0.1.0.0', 'category': 'Discuss', - 'website': 'https://laslabs.com/', + 'website': 'https://github.com/OCA/social', 'author': 'LasLabs, Odoo Community Association (OCA)', 'license': 'LGPL-3', 'application': False, From 5d6806cd22bfa02ddfb8a95e1b8fd997a8753bc7 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Wed, 11 Sep 2019 09:38:41 +0000 Subject: [PATCH 04/51] [UPD] Update mail_outbound_static.pot --- .../i18n/mail_outbound_static.pot | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 mail_outbound_static/i18n/mail_outbound_static.pot diff --git a/mail_outbound_static/i18n/mail_outbound_static.pot b/mail_outbound_static/i18n/mail_outbound_static.pot new file mode 100644 index 000000000..33df369b4 --- /dev/null +++ b/mail_outbound_static/i18n/mail_outbound_static.pot @@ -0,0 +1,30 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mail_outbound_static +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mail_outbound_static +#: model:ir.model.fields,field_description:mail_outbound_static.field_ir_mail_server__smtp_from +msgid "Email From" +msgstr "" + +#. module: mail_outbound_static +#: model:ir.model,name:mail_outbound_static.model_ir_mail_server +msgid "Mail Server" +msgstr "" + +#. module: mail_outbound_static +#: model:ir.model.fields,help:mail_outbound_static.field_ir_mail_server__smtp_from +msgid "Set this in order to email from a specific address." +msgstr "" + From b50d370b43418a7e5e1b348fd311f5562a91ebd3 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 11 Sep 2019 10:00:55 +0000 Subject: [PATCH 05/51] [UPD] README.rst --- mail_outbound_static/static/description/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mail_outbound_static/static/description/index.html b/mail_outbound_static/static/description/index.html index 3ac7728dc..adc409189 100644 --- a/mail_outbound_static/static/description/index.html +++ b/mail_outbound_static/static/description/index.html @@ -3,7 +3,7 @@ - + Mail Outbound Static -
-

Mail Outbound Static

+
+ + +Odoo Community Association + +
+

Mail Outbound Static

-

Beta License: LGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

+

Beta License: LGPL-3 OCA/mail Translate me on Weblate Try me on Runboat

This module brings Odoo outbound emails in to strict compliance with RFC-2822 by allowing for a dynamically configured From header, with the sender’s e-mail being appended into the proper Sender header instead. To accomplish this we:

  • Add a domain whitelist field in the mail server model. This one -represent an allowed Domains list separated by commas. If there is not -given SMTP server it will let us to search the proper mail server to -be used to send the messages where the message ‘From’ email domain +represent an allowed Domains list separated by commas. If there is +not given SMTP server it will let us to search the proper mail server +to be used to send the messages where the message ‘From’ email domain match with the domain whitelist. If there is not mail server that matches then will use the default mail server to send the message.
  • Add a Email From field that will let us to email from a specific @@ -388,8 +393,8 @@

    Mail Outbound Static

    changed because the mail server is able to send in the name of the sender domain.
  • If the original message’s ‘From’ does not match with the domain -whitelist then the email From is replaced with the Email From field -value.
  • +whitelist then the email From is replaced with the Email From +field value.
  • Add compatibility to define the smtp information in Odoo config file. @@ -411,7 +416,7 @@

    Mail Outbound Static

-

Usage

+

Usage

  • Navigate to an Outbound Email Server
  • Set the Email From option to an email address
  • @@ -419,20 +424,20 @@

    Usage

-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

+feedback.

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • braintec AG
  • LasLabs
  • @@ -440,7 +445,7 @@

    Authors

-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -463,10 +468,11 @@

Maintainers

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

-

This module is part of the OCA/mail project on GitHub.

+

This module is part of the OCA/mail project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
diff --git a/mail_outbound_static/tests/test_ir_mail_server.py b/mail_outbound_static/tests/test_ir_mail_server.py index 2b43609d9..25b6252a5 100644 --- a/mail_outbound_static/tests/test_ir_mail_server.py +++ b/mail_outbound_static/tests/test_ir_mail_server.py @@ -3,6 +3,7 @@ import logging import os +import re from email import message_from_string from unittest.mock import patch @@ -72,40 +73,15 @@ def _init_mail_server_domain_whilelist_based(self): } ) - def _send_mail( - self, - message, - mail_server_id=None, - smtp_server=None, - smtp_port=None, - smtp_user=None, - smtp_password=None, - smtp_encryption=None, - smtp_ssl_certificate=None, - smtp_ssl_private_key=None, - smtp_debug=False, - smtp_session=None, - ): - smtp = smtp_session - if not smtp: - smtp = self.IrMailServer.connect( - smtp_server, - smtp_port, - smtp_user, - smtp_password, - smtp_encryption, - smtp_from=message["From"], - ssl_certificate=smtp_ssl_certificate, - ssl_private_key=smtp_ssl_private_key, - smtp_debug=smtp_debug, - mail_server_id=mail_server_id, - ) - - send_from, send_to, message_string = self.IrMailServer._prepare_email_message( - message, smtp - ) - self.IrMailServer.send_email(message) - return message_string + def _send_mail(self, message, mail_server_id=None): + """ + This helper calls the real send_email method. + It's intended to be used inside a `mock_smtplib_connection` + context, which will prevent any real emails from being sent. + The message object is modified in-place and returned for inspection. + """ + self.IrMailServer.send_email(message, mail_server_id=mail_server_id) + return message def test_send_email_injects_from_no_canonical(self): """It should inject the FROM header correctly when no canonical name.""" @@ -397,3 +373,63 @@ def test_11_from_outgoing_server_another_special_char_comma(self): f" but we expect to use {expected_mail_server.name}" ), ) + + def test_12_domain_whitelist_whitespace_handling(self): + """Test whitespace around commas in domain_whitelist.""" + self._init_mail_server_domain_whilelist_based() + mail_server = self.mail_server_domainone + + # This should pass validation due to the .strip() in the list comprehension + mail_server.domain_whitelist = " domainone.com , other.com " + + # Verify it was stored + self.assertTrue(mail_server.domain_whitelist) + + # Test that the error message formatting uses %s correctly + # We pass an invalid domain with spaces to trigger the error + invalid_input = "invalid space" + # The error message in the code uses % (domain) + expected_error = ( + f"{invalid_input} is not a valid domain. Please define a list of" + " valid domains separated by comma" + ) + + with self.assertRaisesRegex(ValidationError, re.escape(expected_error)): + mail_server.domain_whitelist = invalid_input + + def test_13_restore_display_name_after_super_strip(self): + """Test that the display name is restored if super() strips it.""" + self._init_mail_server_domain_whilelist_based() + domain = "domainone.com" + name = "Mitchell Admin" + email = f"admin@{domain}" + # Use tools.formataddr to ensure we match + # the quoting behavior of the implementation + full_from = tools.formataddr((name, email)) + + # Ensure we are using the whitelisted server + mail_server = self.mail_server_domainone + self.assertEqual(mail_server.domain_whitelist, domain) + + self.message.replace_header("From", full_from) + + # Define a side effect to simulate Odoo core stripping the name + # This ensures the modification happens *during* the call, not before + def side_effect(message, smtp_session): + # Simulate Odoo core returning just the email address (name stripped) + # We modify the message object in place as Odoo does + message.replace_header("From", email) + return email, ["to@example.com"], message + + # Patch the method on the class so the super() call inside the module hits this + with patch( + "odoo.addons.base.models.ir_mail_server.IrMail_Server._prepare_email_message__", + side_effect=side_effect, + ): + with self.mock_smtplib_connection(): + # send_email will capture the full context first, then call super(), + # which hits our side_effect, which strips the name. + # Then the module logic should restore it. + result_message = self._send_mail(self.message) + + self.assertEqual(result_message["From"], full_from)