Goal
Enable an Odoo module to automatically send an email to a customer with external attachments, such as a PDF label generated by Sendcloud, as part of a business process. This can apply to a Helpdesk ticket, a sales order, a delivery or an invoice.
Use cases
A few concrete examples of automated document integration:
- Product return via a Helpdesk ticket: sending a return label
- Order confirmation: sending certificates or contractual documents
- Delivery: adding an intervention slip or a delivery acceptance report
- Invoicing: attaching supporting documents or certificates to an invoice or a quotation
Implementation steps
1. Generating or retrieving the external document
The document to attach can be obtained in several ways:
- Automatic generation via an Odoo action (e.g. printing a report)
- Retrieval via a third-party API such as Sendcloud, DocuSign, etc.
- Creation via a scheduled task or custom logic
Once available, the document must be saved in the system as an attachment (ir.attachment). Make sure the attachment has the right information:
label_attachment = self.env['ir.attachment'].create({ 'name': 'etiquette_retour.pdf', 'type': 'binary', 'datas': base64.b64encode(document_bytes), 'res_model': 'stock.picking', # source model 'res_id': picking.id, 'mimetype': 'application/pdf', })
It is essential to make sure the datas field is filled in and contains the encoded file.
2. Copying the attachment to the target business object
To link the document to the business object from which the email will be sent, create a copy of the attachment:
copied_attachment = label_attachment.copy({ 'res_model': self._name, # e.g. helpdesk.ticket, sale.order 'res_id': self.id, 'name': f'document_externe_{self.id}.pdf', })
This copy avoids conflicts between different objects linked to the same file.
3. Sending the email with the attachments injected
The email is sent via a template, using the email_values parameter to force the file to be added:
template.send_mail( self.id, force_send=True, email_values={ 'attachment_ids': [copied_attachment.id] } )
Be careful not to rely only on the report_template field in the template, as this would replace the attachment_ids passed dynamically.
4. Configuring the email template
The email template must be correctly configured. The XML example below illustrates a return label sending case:
Your return label [email protected] <![CDATA[ Hello
, Please find your documents attached.
]]>
The auto_delete field must be set to False to prevent the files from being automatically deleted after sending.
Best practices
- Check that datas is present in each ir.attachment
- Always log the creation and sending of attachments (name, ID, model)
- Always go through an attachment copy to avoid model conflicts
- Do not send the email if no attachment is present
Example of a useful log:
_logger.info("Attachment %s (%s) added to the email of model %s", attachment.name, attachment.id, self._name)
Possible extensions
- Automatic addition of extra documents: signed quotations, certificates, attestations
- Automatic creation of a ZIP archive if several files must be sent together
- Adding a manual button to trigger the sending from the Odoo form
- Logging of sent emails in a dedicated model (e.g. mail.log)
Conclusion
Odoo offers a particularly flexible architecture for automating document sending by email. By combining ir.attachment objects, the options of the email_values parameter, and a clean template configuration, you can cover a large number of business cases without having to develop complex modules.
It is a solid technical foundation for any company wanting to integrate its external documents into its Odoo flows, limiting manual handling and ensuring perfect traceability of what is sent.