Browse Source

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
pull/388/head
Dave Lasley 6 years ago
committed by eLBati
parent
commit
c61d13dc00
  1. 62
      mail_outbound_static/README.rst
  2. 5
      mail_outbound_static/__init__.py
  3. 21
      mail_outbound_static/__manifest__.py
  4. 5
      mail_outbound_static/models/__init__.py
  5. 50
      mail_outbound_static/models/ir_mail_server.py
  6. BIN
      mail_outbound_static/static/description/icon.png
  7. 5
      mail_outbound_static/tests/__init__.py
  8. 70
      mail_outbound_static/tests/test.msg
  9. 70
      mail_outbound_static/tests/test_ir_mail_server.py
  10. 21
      mail_outbound_static/views/ir_mail_server_view.xml

62
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
<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

@ -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

@ -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

@ -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

@ -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

After

Width: 128  |  Height: 128  |  Size: 9.2 KiB

5
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

70
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: <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

@ -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

@ -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…
Cancel
Save