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
This commit is contained in:
parent
6ce2c6af42
commit
85d68c4f40
62
mail_outbound_static/README.rst
Normal file
62
mail_outbound_static/README.rst
Normal file
@ -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
|
||||
<https://github.com/OCA/social/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 <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Dave Lasley <dave@laslabs.com>
|
||||
|
||||
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.
|
5
mail_outbound_static/__init__.py
Normal file
5
mail_outbound_static/__init__.py
Normal file
@ -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
|
21
mail_outbound_static/__manifest__.py
Normal file
21
mail_outbound_static/__manifest__.py
Normal file
@ -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',
|
||||
],
|
||||
}
|
5
mail_outbound_static/models/__init__.py
Normal file
5
mail_outbound_static/models/__init__.py
Normal file
@ -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
|
50
mail_outbound_static/models/ir_mail_server.py
Normal file
50
mail_outbound_static/models/ir_mail_server.py
Normal file
@ -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
|
||||
)
|
BIN
mail_outbound_static/static/description/icon.png
Normal file
BIN
mail_outbound_static/static/description/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
5
mail_outbound_static/tests/__init__.py
Normal file
5
mail_outbound_static/tests/__init__.py
Normal file
@ -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
|
70
mail_outbound_static/tests/test.msg
Normal file
70
mail_outbound_static/tests/test.msg
Normal file
@ -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: <postmaster-odoo@odoo-community.org>
|
||||
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 <test@gmail.com>;
|
||||
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: <A1AAECD6-2A36-45E1-A0F8-4266F178D52C@laslabs.com>
|
||||
references: <0db43737-b846-4890-6801-44ff9617e3b3@camptocamp.com>
|
||||
Subject: Re: OCA Code sprint: sprint topics
|
||||
From: Dave Lasley <test@laslabs.com>
|
||||
Reply-To: "Odoo Community Association \(OCA\) Contributors"
|
||||
<contributors@odoo-community.org>
|
||||
Date: Tue, 12 Sep 2017 17:37:53 -0000
|
||||
List-Id: contributors.odoo-community.org
|
||||
List-Post: <mailto:contributors@odoo-community.org>
|
||||
Precedence: list
|
||||
X-Auto-Response-Suppress: OOF
|
||||
List-Subscribe: <https://odoo-community.org/groups>
|
||||
List-Unsubscribe: <https://odoo-community.org/groups?unsubscribe>
|
||||
List-Archive: <https://odoo-community.org/groups/contributors-15>
|
||||
To: "Contributors" <contributors@odoo-community.org>
|
||||
|
||||
--===============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==--
|
70
mail_outbound_static/tests/test_ir_mail_server.py
Normal file
70
mail_outbound_static/tests/test_ir_mail_server.py
Normal file
@ -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 <test@example.com>' % 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)
|
21
mail_outbound_static/views/ir_mail_server_view.xml
Normal file
21
mail_outbound_static/views/ir_mail_server_view.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright 2017 LasLabs Inc.
|
||||
License LGPL-3 or later (http://www.gnu.org/licenses/lgpl.html).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="ir_mail_server_form" model="ir.ui.view">
|
||||
<field name="name">IR Mail Server - From Address</field>
|
||||
<field name="model">ir.mail_server</field>
|
||||
<field name="inherit_id" ref="base.ir_mail_server_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='smtp_pass']" position="after">
|
||||
<field name="smtp_from" />
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
Loading…
Reference in New Issue
Block a user