diff --git a/attachment_queue_email/README.rst b/attachment_queue_email/README.rst new file mode 100644 index 00000000000..7cee8a78ab1 --- /dev/null +++ b/attachment_queue_email/README.rst @@ -0,0 +1,119 @@ +====================== +Attachment Queue Email +====================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:458802e95b02badcdc94837bdd0e60981bd9d184543efd4a45611ab6b20cfb41 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github + :target: https://github.com/OCA/server-tools/tree/18.0/attachment_queue_email + :alt: OCA/server-tools +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-tools-18-0/server-tools-18-0-attachment_queue_email + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/server-tools&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Abstract module for importing emails attachments. + +Each email's attachment matching a given **"Attachment Condition"** will +be imported creating a new ``attachment.queue`` object. These +``attachment.queue`` objects are files wrapped with additional fields +(mainly a **Filed Type** and a **State**) making them ready to be +processed by a custom module as you can read in the +`attachment_queue `__ +documentation. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Adding an **"Attachment Condition"** to your *Incoming Mail Server* +configuration will lead to the creation of ``attachment.queue`` objects +from emails attachments coming from this server and matching the given +*Attachment Condition*. + + 🔎 Recalling that, as the *Incoming Mail Servers* has only one + *"Create a New Record"* field, the emails coming from that server + **cannot be used to create other type of objects** than + ``attachment.queue``. + +Filling the condition's **File Type** field will spread this value to +the newly created ``attchment.queue`` objects so they can be processed +by a custom module following this **File Type** field value. + +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 `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Akretion + +Contributors +------------ + +- Valentin CHEMIERE +- Florian DA COSTA +- Sebastien BEAU +- Clément Mombereau +- Benoit GUILLOT + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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. + +.. |maintainer-florian-dacosta| image:: https://github.com/florian-dacosta.png?size=40px + :target: https://github.com/florian-dacosta + :alt: florian-dacosta +.. |maintainer-sebastienbeau| image:: https://github.com/sebastienbeau.png?size=40px + :target: https://github.com/sebastienbeau + :alt: sebastienbeau +.. |maintainer-bealdav| image:: https://github.com/bealdav.png?size=40px + :target: https://github.com/bealdav + :alt: bealdav + +Current `maintainers `__: + +|maintainer-florian-dacosta| |maintainer-sebastienbeau| |maintainer-bealdav| + +This module is part of the `OCA/server-tools `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/attachment_queue_email/__init__.py b/attachment_queue_email/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/attachment_queue_email/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/attachment_queue_email/__manifest__.py b/attachment_queue_email/__manifest__.py new file mode 100644 index 00000000000..051130f2237 --- /dev/null +++ b/attachment_queue_email/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2012 Akretion (https://www.akretion.com). +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +{ + "name": "Attachment Queue Email", + "version": "18.0.1.0.0", + "author": "Akretion,Odoo Community Association (OCA)", + "category": "Generic Modules", + "summary": "Create attachment from emails to be processed depending on their type", + "license": "AGPL-3", + "website": "https://github.com/OCA/server-tools", + "maintainers": ["florian-dacosta", "sebastienbeau", "bealdav"], + "depends": ["attachment_queue", "mail"], + "demo": [], + "data": [ + "security/ir.model.access.csv", + "views/fetchmail_attachment_condition.xml", + "views/fetchmail_server.xml", + ], + "installable": True, + "images": [], +} diff --git a/attachment_queue_email/models/__init__.py b/attachment_queue_email/models/__init__.py new file mode 100644 index 00000000000..b95e9fad4c1 --- /dev/null +++ b/attachment_queue_email/models/__init__.py @@ -0,0 +1,3 @@ +from . import attachment_queue +from . import fetchmail_server +from . import fetchmail_attachment_condition diff --git a/attachment_queue_email/models/attachment_queue.py b/attachment_queue_email/models/attachment_queue.py new file mode 100644 index 00000000000..62446c1ca14 --- /dev/null +++ b/attachment_queue_email/models/attachment_queue.py @@ -0,0 +1,105 @@ +# Copyright 2012 Akretion (https://www.akretion.com). +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +import base64 + +from odoo import api, fields, models + + +class AttachmentQueue(models.Model): + _inherit = "attachment.queue" + + fetchmail_attachment_condition_id = fields.Many2one( + "fetchmail.attachment.condition", + string="FetchMail condition", + help="The Fetchmail attachment condition used to create this attachment", + ) + fetchmail_server_id = fields.Many2one( + "fetchmail.server", + string="Email Server", + related="fetchmail_attachment_condition_id.server_id", + store=True, + readonly=True, + help="The email server used to create this attachment", + ) + + @api.model + def _get_attachment_queue_data(self, condition, msg, att): + data = att[1] + # seems files are byte when it comes from zip file so we manage + # both case + if isinstance(data, str): + data = data.encode() + values = { + "fetchmail_attachment_condition_id": condition.id, + "file_type": condition.file_type, + "name": att[0], + "datas": base64.b64encode(data), + "state": "pending", + "company_id": condition.company_id.id, + } + return values + + @api.model + def prepare_data_from_basic_condition(self, cond, msg_dict): + vals_list = [] + # match_from and match_subj are True if empty or if matching with + # msg_dict's values + match_from = ( + cond.email_from + and cond.email_from in msg_dict.get("from", "") + or not cond.email_from + ) + match_subj = ( + cond.email_subject + and cond.email_subject in msg_dict.get("subject", "") + or not cond.email_subject + ) + match_to = ( + cond.email_to + and cond.email_to in msg_dict.get("to", "") + or not cond.email_to + ) + + if match_from and match_subj and match_to: + for att in msg_dict["attachments"]: + if cond.file_extension in att[0] or not cond.file_extension: + vals_list.append( + self._get_attachment_queue_data(cond, msg_dict, att) + ) + return vals_list + + @api.model + def _prepare_data_for_attachment_queue(self, msg_dict): + """Prepare the datas for the creation of one or many attachment.queue depending + on the number of the email's attachments files and if the email matches the + fetchmail.attachment.condition's conditions. + + :param msg_dict: a dictionnary with the email data + :type: dict + + :return: a list of dictionnary that contains the attachment.queue data + :rtype: list + """ + res = [] + server_id = self.env.context.get("default_fetchmail_server_id", False) + file_condition_obj = self.env["fetchmail.attachment.condition"] + conds = file_condition_obj.search([("server_id", "=", server_id)]) + for cond in conds: + vals_list = self.prepare_data_from_basic_condition(cond, msg_dict) + if vals_list: + res += vals_list + return res + + @api.model + def message_new(self, msg_dict, custom_values=None): + """Create Attachments Queues objects from the received email's attachments.""" + # Rewriting completely ``message_new`` instead of overiding it in order to + # allows the creation of many new objects instead of only one. + created_recs = [] + res = self._prepare_data_for_attachment_queue(msg_dict) + if res: + for vals in res: + created_recs.append(self.create(vals)) + return created_recs[0] + return None diff --git a/attachment_queue_email/models/fetchmail_attachment_condition.py b/attachment_queue_email/models/fetchmail_attachment_condition.py new file mode 100644 index 00000000000..583b2acbd9e --- /dev/null +++ b/attachment_queue_email/models/fetchmail_attachment_condition.py @@ -0,0 +1,45 @@ +# Copyright 2012 Akretion (https://www.akretion.com). +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import fields, models + + +class FetchmailAttachmentCondition(models.Model): + _name = "fetchmail.attachment.condition" + _description = "Fetchmail Attachment Conditions" + + name = fields.Char( + string="Condition Name", + required=True, + ) + email_from = fields.Char( + help="If empty, catches the emails from every senders.\n" + "Otherwise catches the emails where the sender's email contains the given " + "characters", + ) + email_to = fields.Char( + help="If empty, catches the email no matter the recipient.\n" + "Otherwise catches the emails where the recipients emails contains the given " + "characters.", + ) + email_subject = fields.Char( + help="If empty, catches the emails with every kind of Subjects.\n" + "Otherwise catches the emails where the Subject contains the given characters", + ) + file_extension = fields.Char( + help="The extension (or part of the name) of the sought files. " + "If empty, all the email's attachments will be imported.", + ) + server_id = fields.Many2one("fetchmail.server", string="Server Mail") + file_type = fields.Selection( + selection=[], + help="The 'file type' is transmited to the 'Attachment Queue' objects created " + "from the selected emails attachments.\nIt will allow Odoo to recognize " + "what do do with them once created.", + ) + company_id = fields.Many2one( + "res.company", + string="Company", + required=True, + default=lambda self: self.env.company, + ) diff --git a/attachment_queue_email/models/fetchmail_server.py b/attachment_queue_email/models/fetchmail_server.py new file mode 100644 index 00000000000..ad04a971ebb --- /dev/null +++ b/attachment_queue_email/models/fetchmail_server.py @@ -0,0 +1,25 @@ +# Copyright 2012 Akretion (https://www.akretion.com). +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import api, fields, models + + +class FetchmailServer(models.Model): + _inherit = "fetchmail.server" + + attachment_condition_ids = fields.One2many( + "fetchmail.attachment.condition", + "server_id", + string="Attachment Condition", + help="Files attached to the emails matching these conditions will be imported " + "in Odoo as 'Attachment Queue' objects", + ) + + @api.onchange("attachment_condition_ids") + def onchange_attachment_condition(self): + for server in self: + if server.attachment_condition_ids: + server.object_id = self.env["ir.model"].search( + [("model", "=", "attachment.queue")] + ) + server.attach = True diff --git a/attachment_queue_email/pyproject.toml b/attachment_queue_email/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/attachment_queue_email/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/attachment_queue_email/readme/CONTRIBUTORS.md b/attachment_queue_email/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..ceb876de84d --- /dev/null +++ b/attachment_queue_email/readme/CONTRIBUTORS.md @@ -0,0 +1,5 @@ +- Valentin CHEMIERE \ +- Florian DA COSTA \ +- Sebastien BEAU \ +- Clément Mombereau \ +- Benoit GUILLOT \ diff --git a/attachment_queue_email/readme/DESCRIPTION.md b/attachment_queue_email/readme/DESCRIPTION.md new file mode 100644 index 00000000000..2d2af96face --- /dev/null +++ b/attachment_queue_email/readme/DESCRIPTION.md @@ -0,0 +1,9 @@ +Abstract module for importing emails attachments. + +Each email's attachment matching a given **"Attachment Condition"** will +be imported creating a new `attachment.queue` object. These +`attachment.queue` objects are files wrapped with additional fields +(mainly a **Filed Type** and a **State**) making them ready to be +processed by a custom module as you can read in the +[attachment_queue](https://github.com/OCA/server-tools/tree/18.0/attachment_queue) +documentation. diff --git a/attachment_queue_email/readme/USAGE.md b/attachment_queue_email/readme/USAGE.md new file mode 100644 index 00000000000..8d3ca619408 --- /dev/null +++ b/attachment_queue_email/readme/USAGE.md @@ -0,0 +1,13 @@ +Adding an **"Attachment Condition"** to your *Incoming Mail Server* +configuration will lead to the creation of `attachment.queue` objects +from emails attachments coming from this server and matching the given +*Attachment Condition*. + +> 🔎 Recalling that, as the *Incoming Mail Servers* has only one +> *"Create a New Record"* field, the emails coming from that server +> **cannot be used to create other type of objects** than +> `attachment.queue`. + +Filling the condition's **File Type** field will spread this value to +the newly created `attchment.queue` objects so they can be processed by +a custom module following this **File Type** field value. diff --git a/attachment_queue_email/security/ir.model.access.csv b/attachment_queue_email/security/ir.model.access.csv new file mode 100644 index 00000000000..68aeab002a2 --- /dev/null +++ b/attachment_queue_email/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_fetchmail_attachment_condition_manager,fetchmail.attachment.condition.manager,model_fetchmail_attachment_condition,base.group_system,1,1,1,1 +access_fetchmail_attachment_condition_user,fetchmail.attachment.condition.user,model_fetchmail_attachment_condition,base.group_user,1,0,0,0 diff --git a/attachment_queue_email/static/description/index.html b/attachment_queue_email/static/description/index.html new file mode 100644 index 00000000000..2b192028c59 --- /dev/null +++ b/attachment_queue_email/static/description/index.html @@ -0,0 +1,452 @@ + + + + + +Attachment Queue Email + + + +
+

Attachment Queue Email

+ + +

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runboat

+

Abstract module for importing emails attachments.

+

Each email’s attachment matching a given “Attachment Condition” will +be imported creating a new attachment.queue object. These +attachment.queue objects are files wrapped with additional fields +(mainly a Filed Type and a State) making them ready to be +processed by a custom module as you can read in the +attachment_queue +documentation.

+

Table of contents

+ +
+

Usage

+

Adding an “Attachment Condition” to your Incoming Mail Server +configuration will lead to the creation of attachment.queue objects +from emails attachments coming from this server and matching the given +Attachment Condition.

+
+🔎 Recalling that, as the Incoming Mail Servers has only one +“Create a New Record” field, the emails coming from that server +cannot be used to create other type of objects than +attachment.queue.
+

Filling the condition’s File Type field will spread this value to +the newly created attchment.queue objects so they can be processed +by a custom module following this File Type field value.

+
+
+

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.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Akretion
  • +
+
+
+

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.

+

Current maintainers:

+

florian-dacosta sebastienbeau bealdav

+

This module is part of the OCA/server-tools project on GitHub.

+

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

+
+
+
+ + diff --git a/attachment_queue_email/tests/__init__.py b/attachment_queue_email/tests/__init__.py new file mode 100644 index 00000000000..c866d7f469f --- /dev/null +++ b/attachment_queue_email/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_attachment_queue_email diff --git a/attachment_queue_email/tests/test_attachment_queue_email.py b/attachment_queue_email/tests/test_attachment_queue_email.py new file mode 100644 index 00000000000..26630c5e9e9 --- /dev/null +++ b/attachment_queue_email/tests/test_attachment_queue_email.py @@ -0,0 +1,74 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.addons.mail.tests.common import MailCommon +from odoo.addons.test_mail.data.test_mail_data import ( + MAIL_MULTIPART_IMAGE, + MAIL_SINGLE_BINARY, +) + + +class TestAttachmentQueueEmail(MailCommon): + def setUp(self): + super().setUp() + self.attach_condition_1 = self.env["fetchmail.attachment.condition"].create( + { + "name": "Attchment Condition 1", + "email_from": "Bruce Wayne", + "file_extension": ".pdf", + } + ) + self.attach_condition_2 = self.env["fetchmail.attachment.condition"].create( + { + "name": "Attchment Condition 2", + "email_subject": "Wonderful pictures", + "file_extension": ".gif", + } + ) + + self.attach_queue_model = self.env["ir.model"].search( + [("model", "=", "attachment.queue")] + ) + self.fetchmail_server = self.env["fetchmail.server"].create( + { + "name": "Test Fetchmail Server 1", + "server_type": "imap", + "attach": True, + "object_id": self.attach_queue_model.id, + "attachment_condition_ids": [ + (6, 0, [self.attach_condition_1.id, self.attach_condition_2.id]) + ], + } + ) + self.context_server = { + "default_fetchmail_server_id": self.fetchmail_server.id, + } + + def test_message_single_binary(self): + """Run message_process on emails with attachment check if an attachment_queue + is created + """ + self.assertFalse( + self.env["attachment.queue"].search([("name", "=", "thetruth.pdf")]) + ) + + self.env["mail.thread"].with_context(**self.context_server).message_process( + self.fetchmail_server.object_id.model, + MAIL_SINGLE_BINARY, + ) + + attach_queue = self.env["attachment.queue"].search( + [("name", "=", "thetruth.pdf")] + ) + self.assertEqual(len(attach_queue), 1) + self.assertEqual(attach_queue.datas, b"SSBhbSB0aGUgQmF0TWFuCg==") + + def test_message_multi_image(self): + mail = MAIL_MULTIPART_IMAGE.format(subject="Wonderful pictures", to="") + + self.env["mail.thread"].with_context(**self.context_server).message_process( + self.fetchmail_server.object_id.model, + mail, + ) + attach_queues = self.env["attachment.queue"].search([("name", "like", ".gif")]) + self.assertEqual(len(attach_queues), 3) + self.assertEqual(attach_queues[0].name, "orangée.gif") diff --git a/attachment_queue_email/views/fetchmail_attachment_condition.xml b/attachment_queue_email/views/fetchmail_attachment_condition.xml new file mode 100644 index 00000000000..d833e748c3b --- /dev/null +++ b/attachment_queue_email/views/fetchmail_attachment_condition.xml @@ -0,0 +1,47 @@ + + + + + view_fetchmail_attachment_condition_tree + fetchmail.attachment.condition + + + + + + + + + + + + + + + view_fetchmail_attachment_condition_form + fetchmail.attachment.condition + +
+ +
+
+ + + + + + + + + + + +
+
+
+
+
diff --git a/attachment_queue_email/views/fetchmail_server.xml b/attachment_queue_email/views/fetchmail_server.xml new file mode 100644 index 00000000000..0f7c855d670 --- /dev/null +++ b/attachment_queue_email/views/fetchmail_server.xml @@ -0,0 +1,14 @@ + + + + fetchmail.server + + + + + + + + + +