Odoo has multiple functions, which can be called in the custom modules to perform different actions. We know that the send_email() method can be called to send an email bypassing required data in it. Also, we can generate pdf reports in different methods from the code. Suppose we need to send an email with the respective report of the customer, In this case, we need to generate the report and send an email with an attachment.
In this blog, we are going to discuss how to send an email with the pdf attachment from the code.
Let us go through the code. Here I will take an example of generating a customer report and then sending the pdf report as an email attachment.
I created a model named “customer. report”. To generate the report. We need fields such as partner_id and line_ids. Where line_ids is an one2many field of account. move. The field template_id is the mail. the template that is required to send an email. In this case, I gave an option to choose the template, hence we used the field template_id.
class CustomerReport(models.Model):
_name = 'customer.report'
_description = "Customer Report"
partner_id = fields.Many2one('res.partner', string="Customer")
template_id = fields.Many2one('mail.template', string='Email Template', domain="[('model','=','customer.report')]",
required=True)
line_ids = fields.One2many('account.move', 'report_id', string="Invoice")
s"
And the form view will look as given below,
Here, we have a generate button in which we generate the account. move via the method action_generate_report. Once we retrieve moves i.e., line_ids, we can move to send the email with the attachment.
def send_email_with_attachment(self):
report_template_id = self.env.ref(
'customer_report.customer_report_pdf_report').render_qweb_pdf(self.id)
data_record = base64.b64encode(report_template_id[0])
ir_values = {
'name': "Customer Report",
'type': 'binary',
'datas': data_record,
'store_fname': data_record,
'mimetype': 'application/x-pdf',
}
data_id = self.env['ir.attachment'].create(ir_values)
template = self.template_id
template.attachment_ids = [(6, 0, [data_id.id])]
email_values = {'email_to': self.partner_id.email,
'email_from': self.env.user.email}
template.send_mail(self.id, email_values=email_values, force_send=True)
template.attachment_ids = [(3, data_id.id)]
return True
In the method send_email_with_attachment(), we have to generate a pdf report for that, we have referred it to the report where id= customer_report_pdf_report which is defined in the xml as shown below.
<report
id="customer_report_pdf_report"
model="customer.report"
string="Customer Report"
report_type="qweb-pdf"
name="customer_report.customer_report_template"
file="customer_report.customer_report_template"
menu="False"
/>
Where name and file is the corresponding template from which we generate pdf. The report template is as shown below.
<odoo>
<data>
<template id="customer_report_template">
<t t-call="web.html_container">
<t t-call="web.internal_layout">
<div class="page">
<div class="row mt64 mb32">
<div class="col-md-12">
<h2 class="text-center">
<span>
Customer Report
</span>
</h2>
</div>
</div>
<div class="row pt-2">
<div class="col-md-12">
<t>
<table class="table table-bordered">
<thead>
<t>
<th class="text-center">Transaction Date</th>
<th class="text-center">Transaction No:</th>
<th class="text-center">Reference</th>
</t>
</thead>
<tbody>
<tr t-foreach="docs.line_ids" t-as="move_id">
<td>
<t t-esc="move_id.invoice_date"/>
</td>
<td>
<t t-esc="move_id.name"/>
</td>
<td>
<t t-esc="move_id.ref"/>
</td>
</tr>
</tbody>
</table>
</t>
</div>
</div>
</div>
</t>
</t>
</template>
</data>
</odoo>
From the template, one can fetch the data and generate the pdf report accordingly. And the generated pdf report looks as,
Once we generate a pdf report, we have to convert it into binary format for that we use the code,
data_record = base64.b64encode(report_template_id[0])
Next is to create an attachment with the pdf. To pass values in the create method we use the following code,
ir_values = {
'name': "Customer Report",
'type': 'binary',
'datas': data_record,
'store_fname': data_record,
'mimetype': 'application/x-pdf',
}
Where data_record is the binary format of the generated pdf. Here mime_type is of the type pdf.
To create an attachment, we have to create a record in the model. attachment with the ir_values as given
data_id = self.env['ir.attachment'].create(ir_values)
Next is to set the email template, hence we have an option to choose the email template, we can assign it to a variable template,
template = self.template_id
Now we attach the attachment ie, data_id to the email template.
template.attachment_ids = [(6, 0, [data_id.id])]
Next is to define the form and to email address, here I pass it via a dictionary. One can directly take user email as email_from address.
email_values = {'email_to': self.partner_id.email,
'email_from': self.env.user.email}
Then we will call the method send_mail from the model mail. template, where we have to pass the email_values.
template.send_mail(self.id, email_values=email_values, force_send=True)
The next step is very important when we attach an attachment to the mail. template, every email which is sent via the respective template will have that attachment in it. To avoid that each time after sending the email, we have to detach attachments from the corresponding email template.
template.attachment_ids = [(3, data_id.id)]
Hope it helps
Thank you