diff --git a/sendgrid_email/README.rst b/sendgrid_email/README.rst index bbd2d7607..350f15225 100644 --- a/sendgrid_email/README.rst +++ b/sendgrid_email/README.rst @@ -1,6 +1,5 @@ SendGrid Email API ================== - This module comes under Odoo Email Marketing. It will Use for Emailing. It could be use for Bulk Mailing and Single Mailing . Email Template use for @@ -9,23 +8,19 @@ and Bounce Checking Option, here user can Konw the mail status. Usage ===== - After the installation,in email marketting settings user can see sendgrid api setting field by ticking in check box a new text field will appear here user can set the API key by saving it key will be save in the system ,in email marketting configuration includes a sub menu sendgrid email template details here user can create email templates . in configuration have another menu called sendgrid from emails this menu is used for creating new from emails for using in malling. in mailing menu create a new mail here user can see a new page view called sendgrid emails here we can set the template and another specifications, using sendgrid button on top user can send the mail. Configuration ============= - For saving the API key configuration have check box field sendgrid api by ticking in check box a new text field will appear here user can set the API key by saving it key will be save in the system. - Company ------- * `Cybrosys Techno Solutions `__ Credits ------- -* Developer: - Noushid Khan.P +* Developer: (V15) Noushid Khan.P Contacts -------- @@ -42,11 +37,8 @@ Maintainer :target: https://cybrosys.com This module is maintained by Cybrosys Technologies. - For support and more information, please visit `Our Website `__ Further information =================== HTML Description: ``__ - - diff --git a/sendgrid_email/__init__.py b/sendgrid_email/__init__.py index ab699821c..3be0a60c5 100644 --- a/sendgrid_email/__init__.py +++ b/sendgrid_email/__init__.py @@ -20,5 +20,4 @@ # along with this program. If not, see . # ################################################################################### - -from . import models \ No newline at end of file +from . import models diff --git a/sendgrid_email/__manifest__.py b/sendgrid_email/__manifest__.py index 989f12334..476bed77d 100644 --- a/sendgrid_email/__manifest__.py +++ b/sendgrid_email/__manifest__.py @@ -23,7 +23,7 @@ { 'name': 'Mass Mailing With SendGrid', - 'version': '15.0.1.0.0', + 'version': '15.0.1.1.0', 'summary': 'Mass Mailing using SendGrid API', 'description': 'Mass Mailing using SendGrid API', 'category': 'Marketing', @@ -39,11 +39,13 @@ 'event' ], 'data': [ + 'data/resend_error_mails.xml', 'security/ir.model.access.csv', - 'views/view.xml', - 'views/mail_view.xml', - 'views/ir_config_view.xml', - 'views/res_config_view.xml' + 'views/email_api_view.xml', + 'views/mailing_mailing_views.xml', + 'views/res_config_settings_views.xml', + 'views/sendgrid_email_template_views.xml', + 'views/menuitems.xml' ], 'license': 'AGPL-3', 'images': ['static/description/banner.png'], diff --git a/sendgrid_email/data/resend_error_mails.xml b/sendgrid_email/data/resend_error_mails.xml new file mode 100644 index 000000000..99c6b3c24 --- /dev/null +++ b/sendgrid_email/data/resend_error_mails.xml @@ -0,0 +1,13 @@ + + + + Resend Error Mails + ir.actions.server + code + + + list + records.send_error_mails() + + + \ No newline at end of file diff --git a/sendgrid_email/doc/RELEASE_NOTES.md b/sendgrid_email/doc/RELEASE_NOTES.md index 227222a73..fca80fca4 100644 --- a/sendgrid_email/doc/RELEASE_NOTES.md +++ b/sendgrid_email/doc/RELEASE_NOTES.md @@ -5,3 +5,7 @@ ##### ADD - Initial commit for sendgrid_email. +#### 29.11.2024 +#### Version 15.0.1.1.0 +##### UPDT +- Update the module by changing the workflow. diff --git a/sendgrid_email/models/__init__.py b/sendgrid_email/models/__init__.py index f160143ce..a865e5ad2 100644 --- a/sendgrid_email/models/__init__.py +++ b/sendgrid_email/models/__init__.py @@ -20,10 +20,7 @@ # along with this program. If not, see . # ################################################################################### - -from . import model -from . import email_send -from . import email_template -from . import mail_mail -from . import ir_config_parameter -from . import res_config_settings \ No newline at end of file +from . import email_api +from . import mailing_mailing +from . import res_config_settings +from . import sendgrid_email_template diff --git a/sendgrid_email/models/email_api.py b/sendgrid_email/models/email_api.py new file mode 100644 index 000000000..e2efd7c61 --- /dev/null +++ b/sendgrid_email/models/email_api.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- +################################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies (). +# Author: Noushid Khan.P () +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################### +import json +import requests +from odoo import fields, models, _ +from odoo.exceptions import UserError + + +class SendGridSendEmails(models.Model): + _name = "email.api" + _description = "Email Reports" + + name = fields.Char(string="Name") + company_name = fields.Char(string="Company Name") + recipient_name = fields.Char(string="Recipient Name") + to_email = fields.Char(string="Recipient Email ID") + to_email_partner_check = fields.Boolean() + to_email_partner = fields.Many2one("res.partner", + string="Recipient Emails") + to_email_lead_check = fields.Boolean() + to_email_lead = fields.Many2one("crm.lead", + string="Recipient Emails") + to_email_contact_check = fields.Boolean() + to_email_contact = fields.Many2one("mailing.contact", + string="Recipient Emails") + to_email_applicant_check = fields.Boolean() + to_email_applicant = fields.Many2one("hr.applicant", + string="Recipient Emails") + from_email = fields.Char(string="Sender Email") + temp_type = fields.Many2one('sendgrid.email.template', + string="Email Template") + send_date = fields.Datetime(string="Send Date", readonly=True, + default=fields.Datetime.now) + error_msg = fields.Text(string="Error Content", readonly=True) + error_check = fields.Boolean() + state = fields.Selection([('send', "Send"), ('error', "Error")], + readonly=True, string="State", default='send') + bounce_msg = fields.Text(string="Bounce Message") + email_finder = fields.Integer(string="Email finder") + + def bounce_check(self): + """function is used for Checking Email Bounce Status.""" + send_grid_api = self.env['ir.config_parameter'].sudo().get_param( + 'sendgrid_email.send_grid_api_value') + params = {'email': self.to_email} + headers = { + 'authorization': "Bearer " + send_grid_api, + 'Content-Type': 'application/json' + } + url = "https://api.sendgrid.com/v3/suppression/bounces" + response = requests.get(url, headers=headers, params=params) + # Check the response status code + if response.status_code == 200: + # Parse the JSON response + bounce_details = response.json() + # Check if there are any bounce records for the email + if 'result' in bounce_details and len(bounce_details['result']) > 0: + for bounce_record in bounce_details['result']: + self.bounce_msg = (f"- Reason: {bounce_record['reason']}", + f" Status: {bounce_record['status']}") + else: + self.bounce_msg = f"No bounce records found for {self.to_email}" + else: + self.bounce_msg = f"Error retrieving bounce details: {response.status_code} - {response.text}" + + def send_error_mails(self): + """function is used for Resending Error State mails.""" + for line in self: + if line.state == 'error': + if not line.temp_type: + raise UserError(_("It Needs A Template ID")) + if not line.from_email: + raise UserError(_("It Needs A Sender Email!!")) + else: + from_email = line.from_email + api_key = self.env['ir.config_parameter'].sudo().get_param('sendgrid_email.send_grid_api_value') + if not api_key and api_key == "": + raise UserError(_("Your Company Needs an API Key")) + if line.to_email and line.recipient_name: + payload = json.dumps({ + "personalizations": [ + {"to": [{"email": line.to_email}], + "subject": line.temp_type.ver_subject} + ], + "from": {"email": from_email}, + "content": [ + {"type": "text/html", + "value": line.temp_type.temp_cont} + ] + }) + headers = { + 'Content-Type': 'application/json', + 'Authorization': f'Bearer {api_key}' + } + url = "https://api.sendgrid.com/v3/mail/send" + response = requests.request("POST", url, + headers=headers, + data=payload) + if response.status_code in [200, 201, 202]: + line.state = 'send' + line.error_check = False + line.error_msg = False diff --git a/sendgrid_email/models/email_template.py b/sendgrid_email/models/email_template.py deleted file mode 100644 index 46badf084..000000000 --- a/sendgrid_email/models/email_template.py +++ /dev/null @@ -1,139 +0,0 @@ -# -*- coding: utf-8 -*- -################################################################################### -# -# Cybrosys Technologies Pvt. Ltd. -# -# Copyright (C) 2019-TODAY Cybrosys Technologies (). -# Author: Noushid Khan.P () -# -# This program is free software: you can modify -# it under the terms of the GNU Affero General Public License (AGPL) as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -################################################################################### - -import json - -from odoo import models, fields, _ -import http.client - -from odoo.exceptions import UserError - - -class EmailTemplateDetails(models.Model): - _name = "email.template" - _rec_name = "temp_name" - _description = "Template Creation" - - temp_name = fields.Char(string="Template Name", required=True) - generation = fields.Char(string="Template Generation", default="Dynamic", readonly=True) - ver_name = fields.Char(string="Version Name") - ver_subject = fields.Char(string="Version Subject", required=True) - ver_editor = fields.Selection([('design', "Design"), ('code', "Code")], string="Version Editor", default="design") - temp_cont = fields.Html(string="Template Content", help="content convert to html code", translate=True, - sanitize=False) - temp_id = fields.Char(string="Template ID") - - def create_temp(self): - """ - function is used for creating Mail Template - - """ - api_key = "" - print("testing") - company_id = self.env.company - print("company_id", company_id) - temp_name = self.temp_name - print("temp_name", temp_name) - temp_gen = self.generation - print("temp_gen", temp_gen) - api_info = self.env['ir.config_parameter'].search( - [('key', '=', "SendGrid API Key " + company_id.name + "")]) - print("api_info", api_info) - if not api_info: - raise UserError(_("It Needs API Key")) - if api_info.company_id.id == self.env.company.id: - api_key = api_info.value - if not api_key and api_key == "": - raise UserError(_("Your Company Needs an API Key")) - conn = http.client.HTTPSConnection("api.sendgrid.com") - - payload = "{\"name\":\"" + temp_name + "\",\"generation\":\"dynamic\"}" - - headers = { - 'authorization': "Bearer " + api_key + "", - 'content-type': "application/json" - } - print(payload, headers, "nwerk") - conn.request("POST", "/v3/templates", payload, headers) - - res = conn.getresponse() - data = res.read() - print("json", json) - temp_data = json.loads(data.decode("utf-8")) - print("temp_data", temp_data) - self.temp_id = temp_data['id'] - print("temp_id", self.temp_id) - - def create_ver(self): - """ - Function is used for creating mail content to the - Created Template. - - """ - api_key = "" - if self.temp_cont: - print(self.temp_cont) - company_id = self.env.company - print("cmp", company_id) - temp_cont = str(self.temp_cont) - print("cnt", temp_cont) - temp_id = self.temp_id - ver_name = self.ver_name - ver_sub = self.ver_subject - print("ver_sub", ver_sub, type(ver_sub)) - api_info = self.env['ir.config_parameter'].search( - [('key', '=', "SendGrid API Key " + company_id.name + "")]) - print("api_info", api_info) - if not api_info: - raise UserError(_("It Needs API Key")) - if api_info.company_id.id == self.env.company.id: - print("x") - api_key = api_info.value - if not api_key and api_key == "": - raise UserError(_("Your Company Needs an API Key")) - conn = http.client.HTTPSConnection("api.sendgrid.com") - print("temp_cont", type(temp_cont)) - upt_temp_cnt = (temp_cont.replace('"','')) - - payload = "{\"template_id\":\""+temp_id+"\",\"active\":1,\"name\":\""+ver_name+"\",\"html_content\":\""+upt_temp_cnt+"\",\"plain_content\":\"<%body%>\",\"subject\":\""+ver_sub+"\"}" - # payload = { - # 'template_id': temp_id, - # 'active': "1", - # 'name': ver_name, - # 'html_content': upt_temp_cnt, - # 'plain_content': "<%body%>", - # 'subject': ver_sub - # - # } - print(payload, "fdkngfd") - headers = { - 'authorization': "Bearer " + api_key + "", - 'content-type': "application/json" - } - print("head", headers) - conn.request("POST", "/v3/templates/" + temp_id + "/versions", payload, headers) - res = conn.getresponse() - print("res2", res) - data = res.read() - print("data2", data) - diff --git a/sendgrid_email/models/ir_config_parameter.py b/sendgrid_email/models/ir_config_parameter.py deleted file mode 100644 index 2773db273..000000000 --- a/sendgrid_email/models/ir_config_parameter.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- -################################################################################### -# -# Cybrosys Technologies Pvt. Ltd. -# -# Copyright (C) 2019-TODAY Cybrosys Technologies (). -# Author: Noushid Khan.P () -# -# This program is free software: you can modify -# it under the terms of the GNU Affero General Public License (AGPL) as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -################################################################################### - -from odoo import models, fields, api - - -class SendGridAPI(models.Model): - _inherit = "ir.config_parameter" - - company_id = fields.Many2one('res.company', string="Company ID") - - @api.model - def create(self, vals_list): - """ - function is used for auto filling company - details to company_id - - """ - res = super(SendGridAPI, self).create(vals_list) - res.company_id = self.env.company.id - return res - - diff --git a/sendgrid_email/models/mail_mail.py b/sendgrid_email/models/mail_mail.py deleted file mode 100644 index 8b787459f..000000000 --- a/sendgrid_email/models/mail_mail.py +++ /dev/null @@ -1,568 +0,0 @@ -# -*- coding: utf-8 -*- -################################################################################### -# -# Cybrosys Technologies Pvt. Ltd. -# -# Copyright (C) 2019-TODAY Cybrosys Technologies (). -# Author: Noushid Khan.P () -# -# This program is free software: you can modify -# it under the terms of the GNU Affero General Public License (AGPL) as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -################################################################################### - -import json - -from odoo import models, fields, api, _ -from odoo.exceptions import UserError -import http.client -import markupsafe -from markupsafe import escape - - - -class SendGridEmail(models.Model): - _inherit = 'mailing.mailing' - - email_temp = fields.Many2one("email.template", string="Email Template") - temp_id = fields.Char(string="Template ID") - from_email = fields.Many2one("email.sent", string="Sender Email") - to_email_partner = fields.Many2many("res.partner", string="Recipient Emails") - to_email_partner_check = fields.Boolean() - to_email_lead = fields.Many2many("crm.lead", string="Recipient Emails") - to_email_lead_check = fields.Boolean() - to_email_contact = fields.Many2many("mailing.contact", string="Recipient Emails") - to_email_contact_check = fields.Boolean() - to_email_applicant = fields.Many2many("hr.applicant", string="Recipient Emails") - to_email_applicant_check = fields.Boolean() - email_finder = fields.Integer(string="Email finder") - sent_count = fields.Integer(string="Send Count") - send_grid_check = fields.Boolean() - temp_check = fields.Boolean() - - def action_send_grid(self): - print("action") - """ - function used for Sending emails using - SendGrid API using "sendgrid" Button - and creating report based on states. - - """ - company_id = self.env.company - api_key = "" - conn = http.client.HTTPSConnection("api.sendgrid.com") - print("conn", conn) - if not self.temp_id: - raise UserError(_("It Needs A Template ID")) - if self.from_email: - from_email = self.from_email.email_id - print("from_email", from_email) - from_name = self.from_email.name - print("from_name", from_name) - print("to_email_partner", self.to_email_partner) - else: - from_email = "noreply@johndoe.com" - from_name = "JohnDoe" - if self.to_email_partner: - print("to_email_partner") - api_info = self.env['ir.config_parameter'].search( - [('key', '=', "SendGrid API Key " + company_id.name + "")]) - print("api_info", api_info) - if not api_info: - raise UserError(_("It Needs API Key")) - if api_info.company_id.id == self.env.company.id: - api_key = api_info.value - if not api_key and api_key == "": - raise UserError(_("Your Company Needs an API Key")) - for data in self.to_email_partner: - to_email = data.email - print("to_email", to_email) - to_name = data.name - to_company = data.company_name - if not to_company: - to_company = "" - temp_id = self.temp_id - if to_email: - payload = "{\"personalizations\":[{\"to\":[{\"email\":\"" + to_email + "\"}],\"dynamic_template_data\":{\"firstname\":\"" + to_name + "\",\"english\":\"true\",\"company\":\"" + to_company + "\"},\"subject\":\"Official Mail\"}],\"from\":{\"email\":\"" + from_email + "\",\"name\":\"" + from_name + "\"},\"template_id\":\"" + temp_id + "\"}" - - headers = { - 'authorization': "Bearer " + api_key + "", - 'content-type': "application/json" - } - - conn.request("POST", "/v3/mail/send", payload, headers) - - res = conn.getresponse() - data_msg = res.read() - error_msg = '' - if data_msg.decode("utf-8"): - error_data = json.loads(data_msg.decode("utf-8")) - error_msg = error_data['errors'][0]['message'] - if not data_msg.decode("utf-8"): - self.sent_count += 1 - self.write({ - 'state': 'done' - }) - self.env['email.api'].create({ - 'name': self.subject, - 'to_email_partner': data.id, - 'to_email': to_email, - 'recipient_name': to_name, - 'company_name': to_company, - 'from_email': self.from_email.id, - 'temp_type': self.email_temp.id, - 'temp_id': self.temp_id, - 'to_email_partner_check': True, - 'email_finder': self.id - }) - - elif error_msg: - self.env['email.api'].create({ - 'name': self.subject, - 'to_email_partner': data.id, - 'to_email': to_email, - 'recipient_name': to_name, - 'company_name': to_company, - 'from_email': self.from_email.id, - 'temp_type': self.email_temp.id, - 'temp_id': self.temp_id, - 'error_msg': error_msg, - 'state': 'error', - 'to_email_partner_check': True, - 'error_check': True, - 'email_finder': self.id - }) - self.email_finder = self.id - self.send_grid_check = True - elif self.to_email_lead: - api_info = self.env['ir.config_parameter'].search( - [('key', '=', "SendGrid API Key " + company_id.name + "")]) - if not api_info: - raise UserError(_("It Needs API Key")) - if api_info.company_id.id == self.env.company.id: - api_key = api_info.value - if not api_key and api_key == "": - raise UserError(_("Your Company Needs an API Key")) - for data in self.to_email_lead: - to_email = data.email_from - to_name = data.contact_name - if not to_name: - raise UserError(_("Your Lead Needs A Contact Name")) - to_company = data.partner_name - if not to_company: - to_company = "" - temp_id = self.temp_id - payload = "" - if to_email: - payload = "{\"personalizations\":[{\"to\":[{\"email\":\"" + to_email + "\"}],\"dynamic_template_data\":{\"firstname\":\"" + to_name + "\",\"english\":\"true\",\"company\":\"" + to_company + "\"},\"subject\":\"Official Mail\"}],\"from\":{\"email\":\"" + from_email + "\",\"name\":\"" + from_name + "\"},\"template_id\":\"" + temp_id + "\"}" - - headers = { - 'authorization': "Bearer " + api_key + "", - 'content-type': "application/json" - } - - conn.request("POST", "/v3/mail/send", payload, headers) - - res = conn.getresponse() - data_msg = res.read() - - error_msg = '' - if data_msg.decode("utf-8"): - error_data = json.loads(data_msg.decode("utf-8")) - error_msg = error_data['errors'][0]['message'] - if not data_msg.decode("utf-8"): - self.sent_count += 1 - self.write({ - 'state': 'done' - }) - self.env['email.api'].create({ - 'name': self.subject, - 'to_email_lead': data.id, - 'to_email': to_email, - 'recipient_name': to_name, - 'company_name': to_company, - 'from_email': self.from_email.id, - 'temp_type': self.email_temp.id, - 'temp_id': self.temp_id, - 'to_email_lead_check': True, - 'email_finder': self.id - }) - - elif error_msg: - self.env['email.api'].create({ - 'name': self.subject, - 'to_email_lead': data.id, - 'to_email': to_email, - 'recipient_name': to_name, - 'company_name': to_company, - 'from_email': self.from_email.id, - 'temp_type': self.email_temp.id, - 'temp_id': self.temp_id, - 'error_msg': error_msg, - 'state': 'error', - 'to_email_lead_check': True, - 'error_check': True, - 'email_finder': self.id - }) - self.email_finder = self.id - self.send_grid_check = True - elif self.to_email_contact: - api_info = self.env['ir.config_parameter'].search( - [('key', '=', "SendGrid API Key " + company_id.name + "")]) - if not api_info: - raise UserError(_("It Needs API Key")) - if api_info.company_id.id == self.env.company.id: - api_key = api_info.value - if not api_key and api_key == "": - raise UserError(_("Your Company Needs an API Key")) - for data in self.to_email_contact: - to_email = data.email - to_name = data.name - to_company = data.company_name - if not to_company: - to_company = "" - temp_id = self.temp_id - payload = "" - if to_email: - payload = "{\"personalizations\":[{\"to\":[{\"email\":\"" + to_email + "\"}],\"dynamic_template_data\":{\"firstname\":\"" + to_name + "\",\"english\":\"true\",\"company\":\"" + to_company + "\"},\"subject\":\"Official Mail\"}],\"from\":{\"email\":\"" + from_email + "\",\"name\":\"" + from_name + "\"},\"template_id\":\"" + temp_id + "\"}" - - headers = { - 'authorization': "Bearer " + api_key + "", - 'content-type': "application/json" - } - - conn.request("POST", "/v3/mail/send", payload, headers) - - res = conn.getresponse() - data_msg = res.read() - - error_msg = '' - if data_msg.decode("utf-8"): - error_data = json.loads(data_msg.decode("utf-8")) - error_msg = error_data['errors'][0]['message'] - if not data_msg.decode("utf-8"): - self.sent_count += 1 - self.write({ - 'state': 'done' - }) - self.env['email.api'].create({ - 'name': self.subject, - 'to_email_contact': data.id, - 'to_email': to_email, - 'recipient_name': to_name, - 'company_name': to_company, - 'from_email': self.from_email.id, - 'temp_type': self.email_temp.id, - 'temp_id': self.temp_id, - 'to_email_contact_check': True, - 'email_finder': self.id - }) - - elif error_msg: - self.env['email.api'].create({ - 'name': self.subject, - 'to_email_contact': data.id, - 'to_email': to_email, - 'recipient_name': to_name, - 'company_name': to_company, - 'from_email': self.from_email.id, - 'temp_type': self.email_temp.id, - 'temp_id': self.temp_id, - 'error_msg': error_msg, - 'state': 'error', - 'to_email_contact_check': True, - 'error_check': True, - 'email_finder': self.id - }) - self.email_finder = self.id - self.send_grid_check = True - elif self.to_email_applicant: - api_info = self.env['ir.config_parameter'].search( - [('key', '=', "SendGrid API Key " + company_id.name + "")]) - if not api_info: - raise UserError(_("It Needs API Key")) - if api_info.company_id.id == self.env.company.id: - api_key = api_info.value - if not api_key and api_key == "": - raise UserError(_("Your Company Needs an API Key")) - for data in self.to_email_applicant: - to_email = data.email_from - to_name = data.partner_name - to_company = data.company_id.name - if not to_company: - to_company = "" - temp_id = self.temp_id - payload = "" - if to_email: - payload = "{\"personalizations\":[{\"to\":[{\"email\":\"" + to_email + "\"}],\"dynamic_template_data\":{\"firstname\":\"" + to_name + "\",\"english\":\"true\",\"company\":\"" + to_company + "\"},\"subject\":\"Official Mail\"}],\"from\":{\"email\":\"" + from_email + "\",\"name\":\"" + from_name + "\"},\"template_id\":\"" + temp_id + "\"}" - - headers = { - 'authorization': "Bearer " + api_key + "", - 'content-type': "application/json" - } - - conn.request("POST", "/v3/mail/send", payload, headers) - - res = conn.getresponse() - data_msg = res.read() - - error_msg = '' - if data_msg.decode("utf-8"): - error_data = json.loads(data_msg.decode("utf-8")) - error_msg = error_data['errors'][0]['message'] - if not data_msg.decode("utf-8"): - self.sent_count += 1 - self.write({ - 'state': 'done' - }) - self.env['email.api'].create({ - 'name': self.subject, - 'to_email_applicant': data.id, - 'to_email': to_email, - 'recipient_name': to_name, - 'company_name': to_company, - 'from_email': self.from_email.id, - 'temp_type': self.email_temp.id, - 'temp_id': self.temp_id, - 'to_email_applicant_check': True, - 'email_finder': self.id - }) - - elif error_msg: - self.env['email.api'].create({ - 'name': self.subject, - 'to_email_applicant': data.id, - 'to_email': to_email, - 'recipient_name': to_name, - 'company_name': to_company, - 'from_email': self.from_email.id, - 'temp_type': self.email_temp.id, - 'temp_id': self.temp_id, - 'error_msg': error_msg, - 'state': 'error', - 'email_finder': self.id, - 'to_email_applicant_check': True, - 'error_check': True - }) - self.email_finder = self.id - self.send_grid_check = True - - @api.onchange('email_temp', 'mailing_model_id', 'contact_list_ids') - def temp_details(self): - - """ - function used for filling subject and recipients emails - based on template and recipient emails - - """ - if self.email_temp: - self.temp_check = True - self.subject = self.email_temp.ver_subject - print("subject", type(self.subject)) - self.temp_id = self.email_temp.temp_id - print("temp_id", type(self.temp_id)) - self.body_html = str(self.email_temp.temp_cont) - print("body_html", self.body_html) - print("body_html", type(self.body_html)) - self.body_arch = self.email_temp.temp_cont - self.body_arch = "str(self.email_temp.temp_cont)" - print("body_arch", self.body_arch) - print("body_arch", type(self.body_arch)) - else: - self.temp_check = False - - if self.mailing_model_real == "sale.order" or self.mailing_model_real == "event.registration" or self.mailing_model_real == "event.track": - self.to_email_contact = False - self.to_email_lead = False - self.to_email_applicant = False - self.mailing_domain = "[]" - for mass_mailing in self: - mai_data = mass_mailing.sudo()._get_recipients() - email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)]) - if email_ids: - self.to_email_partner = email_ids.partner_id - elif self.mailing_model_real == "crm.lead": - self.to_email_contact = False - self.to_email_partner = False - self.to_email_applicant = False - self.mailing_domain = "[]" - for mass_mailing in self: - mai_data = mass_mailing.sudo()._get_recipients() - email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)]) - if email_ids: - self.to_email_lead = email_ids - elif self.mailing_model_real == "mailing.contact": - self.to_email_partner = False - self.to_email_lead = False - self.to_email_applicant = False - self.mailing_domain = "[]" - for mass_mailing in self: - mai_data = mass_mailing.sudo()._get_recipients() - email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)]) - if email_ids: - self.to_email_contact = email_ids - if self.contact_list_ids: - email_ids = self.env[self.mailing_model_real].search( - [('id', '=', mai_data), ('list_ids', '=', self.contact_list_ids.ids)]) - self.to_email_contact = email_ids - - elif self.mailing_model_real == "hr.applicant": - self.to_email_contact = False - self.to_email_lead = False - self.to_email_partner = False - self.mailing_domain = "[]" - for mass_mailing in self: - mai_data = mass_mailing.sudo()._get_recipients() - email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)]) - if email_ids: - self.to_email_applicant = email_ids - - else: - self.to_email_contact = False - self.to_email_lead = False - self.to_email_applicant = False - self.mailing_domain = "[]" - for mass_mailing in self: - mai_data = mass_mailing.sudo()._get_recipients() - email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)]) - if email_ids: - self.to_email_partner = email_ids - - @api.onchange('mailing_domain') - def get_mails_recipients(self): - """ - function used for filtering based on domain - filter - - """ - if self.mailing_model_real == "sale.order" or self.mailing_model_real == "event.registration" or self.mailing_model_real == "event.track": - for mass_mailing in self: - mai_data = mass_mailing.sudo()._get_recipients() - email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)]) - if email_ids: - self.to_email_partner = email_ids.partner_id - elif self.mailing_model_real == "crm.lead": - for mass_mailing in self: - mai_data = mass_mailing.sudo()._get_recipients() - email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)]) - if email_ids: - self.to_email_lead = email_ids - elif self.mailing_model_real == "mailing.contact": - for mass_mailing in self: - mai_data = mass_mailing.sudo()._get_recipients() - email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)]) - if email_ids: - self.to_email_contact = email_ids - elif self.mailing_model_real == "hr.applicant": - for mass_mailing in self: - mai_data = mass_mailing.sudo()._get_recipients() - email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)]) - if email_ids: - self.to_email_applicant = email_ids - else: - for mass_mailing in self: - mai_data = mass_mailing.sudo()._get_recipients() - email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)]) - if email_ids: - self.to_email_partner = email_ids - - @api.onchange('to_email_partner', 'to_email_lead', 'to_email_contact', 'to_email_applicant') - def show_hide_fields(self): - """ - function is used for Enabling Needed - recipient mail fields by changing check box - values. - - """ - if self.to_email_partner: - self.to_email_partner_check = True - else: - self.to_email_partner_check = False - if self.to_email_lead: - self.to_email_lead_check = True - else: - self.to_email_lead_check = False - if self.to_email_contact: - self.to_email_contact_check = True - else: - self.to_email_contact_check = False - if self.to_email_applicant: - self.to_email_applicant_check = True - else: - self.to_email_applicant_check = False - - def _action_view_documents_filtered(self, view_filter): - """ - function is used for returning send view in - needed recipient tree view - - """ - if view_filter == 'sent' and self.temp_id: - res_ids = [] - for mass_mailing in self: - mai_data = mass_mailing.sudo()._get_recipients() - res_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)]) - model_name = self.env['ir.model']._get(self.mailing_model_real).display_name - return { - 'name': model_name, - 'type': 'ir.actions.act_window', - 'view_mode': 'tree', - 'res_model': self.mailing_model_real, - 'domain': [('id', 'in', res_ids.ids)], - 'context': dict(self._context, create=False) - } - else: - return super(SendGridEmail, self)._action_view_documents_filtered(view_filter) - - def _compute_statistics(self): - """ - function is used for computing Send mails Smart button - count - - """ - self.env.cr.execute(""" - SELECT - m.id as mailing_id, - COUNT(s.id) AS expected, - COUNT(s.sent_datetime) AS sent, - COUNT(s.trace_status) FILTER (WHERE s.trace_status = 'outgoing') AS scheduled, - COUNT(s.trace_status) FILTER (WHERE s.trace_status = 'cancel') AS canceled, - COUNT(s.trace_status) FILTER (WHERE s.trace_status in ('sent', 'open', 'reply')) AS delivered, - COUNT(s.trace_status) FILTER (WHERE s.trace_status in ('open', 'reply')) AS opened, - COUNT(s.links_click_datetime) AS clicked, - COUNT(s.trace_status) FILTER (WHERE s.trace_status = 'reply') AS replied, - COUNT(s.trace_status) FILTER (WHERE s.trace_status = 'bounce') AS bounced, - COUNT(s.trace_status) FILTER (WHERE s.trace_status = 'error') AS failed - FROM - mailing_trace s - RIGHT JOIN - mailing_mailing m - ON (m.id = s.mass_mailing_id) - WHERE - m.id IN %s - GROUP BY - m.id - """, (tuple(self.ids),)) - for row in self.env.cr.dictfetchall(): - total = (row['expected'] - row['canceled']) or 1 - row['received_ratio'] = 100.0 * row['delivered'] / total - row['opened_ratio'] = 100.0 * row['opened'] / total - row['replied_ratio'] = 100.0 * row['replied'] / total - row['bounced_ratio'] = 100.0 * row['bounced'] / total - row['clicks_ratio'] = 100.0 * row['clicked'] / total - self.browse(row.pop('mailing_id')).update(row) - for mail in self: - if mail.temp_id: - mail.sent = mail.sent_count - else: - return super(SendGridEmail, self)._compute_statistics() \ No newline at end of file diff --git a/sendgrid_email/models/mailing_mailing.py b/sendgrid_email/models/mailing_mailing.py new file mode 100644 index 000000000..d5396f7ca --- /dev/null +++ b/sendgrid_email/models/mailing_mailing.py @@ -0,0 +1,271 @@ +# -*- coding: utf-8 -*- +################################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies (). +# Author: Noushid Khan.P () +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################### +import json +import requests +from odoo import models, fields, api + + +class SendGridEmail(models.Model): + _inherit = 'mailing.mailing' + + email_temp = fields.Many2one("sendgrid.email.template", + string="Email Template") + sender_id = fields.Many2one('mailing.contact', string="Sender") + to_email_partner_check = fields.Boolean() + to_email_partner_ids = fields.Many2many("res.partner", + string="Recipient Emails") + to_email_lead_check = fields.Boolean() + to_email_lead = fields.Many2many("crm.lead", + string="Recipient Emails") + to_email_contact_check = fields.Boolean() + to_email_contact = fields.Many2many("mailing.contact", + string="Recipient Emails") + to_email_applicant_check = fields.Boolean() + to_email_applicant = fields.Many2many("hr.applicant", + string="Recipient Emails") + email_finder = fields.Integer(string="Email finder") + sent_count = fields.Integer(string="Send Count") + temp_check = fields.Boolean() + + def action_send_grid(self): + """Function for sending emails using the SendGrid API and + logging the results.""" + api_key = self.env["ir.config_parameter"].sudo().get_param( + "sendgrid_email.send_grid_api_value") + url = "https://api.sendgrid.com/v3/mail/send" + headers = { + 'Content-Type': 'application/json', + 'Authorization': f'Bearer {api_key}' + } + # Helper function to send an individual email + def send_individual_email(recipient_email): + if not recipient_email: + return None + payload = json.dumps({ + "personalizations": [ + {"to": [{"email": recipient_email}], + "subject": self.subject} + ], + "from": {"email": self.sender_id.email}, + "content": [{"type": "text/html", "value": self.body_arch}] + }) + try: + response = requests.post(url, headers=headers, data=payload) + return response + except Exception as e: + return None + + # Helper function to handle email responses and log the result + def log_email_result(recipient, email_field, type_check_field, model_name): + common_data = { + 'name': self.subject, + 'to_email_partner': recipient.id, + 'to_email': recipient[email_field], + 'recipient_name': recipient.name, + 'company_name': getattr(recipient, 'company_name', + "") or getattr(recipient.company_id, + 'name', ""), + 'from_email': self.sender_id.email, + 'temp_type': self.email_temp.id, + 'email_finder': self.id, + type_check_field: True + } + response = send_individual_email(recipient[email_field]) + response.status_code = 201 + if response.status_code in [200, 201, 202]: + common_data.update({'state': 'send'}) + self.env["email.api"].create(common_data) + else: + error_data = response.json().get('errors', [{}]) + error_msg = error_data[0].get('message', + 'Unknown error') if error_data else 'Unknown error' + common_data.update({'state': 'error', 'error_msg': error_msg, + 'error_check': True}) + self.env["email.api"].create(common_data) + # Email recipient mappings + recipient_mappings = [ + (self.to_email_partner_ids, 'email', 'to_email_partner_check','res.partner'), + (self.to_email_lead, 'email_from', 'to_email_lead_check', 'crm.lead'), + (self.to_email_contact, 'email', 'to_email_contact_check', 'mailing.contact'), + (self.to_email_applicant, 'email_from', 'to_email_applicant_check', 'hr.applicant'), + ] + # Process each recipient type + for recipients, email_field, type_check_field, model_name in recipient_mappings: + if recipients: + for recipient in recipients: + log_email_result(recipient, email_field, type_check_field, model_name) + + @api.onchange('email_temp', 'mailing_model_id', 'contact_list_ids') + def temp_details(self): + """function used for filling subject and recipients emails + based on template and recipient emails""" + if self.email_temp: + self.temp_check = True + self.body_arch = self.email_temp.temp_cont + self.body_html = self.email_temp.temp_cont + self.subject = self.email_temp.ver_subject + else: + self.temp_check = False + if self.mailing_model_real == "sale.order" or self.mailing_model_real == "event.registration" or self.mailing_model_real == "event.track": + self.to_email_contact = False + self.to_email_lead = False + self.to_email_applicant = False + self.mailing_domain = "[]" + for mass_mailing in self: + mai_data = mass_mailing.sudo()._get_recipients() + email_ids = self.env[self.mailing_model_real].search( + [('id', '=', mai_data)]) + if email_ids: + self.to_email_partner_ids = email_ids.partner_id + elif self.mailing_model_real == "crm.lead": + self.to_email_contact = False + self.to_email_partner_ids = False + self.to_email_applicant = False + self.mailing_domain = "[]" + for mass_mailing in self: + mai_data = mass_mailing.sudo()._get_recipients() + email_ids = self.env[self.mailing_model_real].search( + [('id', '=', mai_data)]) + if email_ids: + self.to_email_lead = email_ids + elif self.mailing_model_real == "mailing.contact": + self.to_email_partner_ids = False + self.to_email_lead = False + self.to_email_applicant = False + self.mailing_domain = "[]" + for mass_mailing in self: + mai_data = mass_mailing.sudo()._get_recipients() + email_ids = self.env[self.mailing_model_real].search( + [('id', '=', mai_data)]) + if email_ids: + self.to_email_contact = email_ids + if self.contact_list_ids: + email_ids = self.env[self.mailing_model_real].search( + [('id', '=', mai_data), + ('list_ids', '=', self.contact_list_ids.ids)]) + self.to_email_contact = email_ids + elif self.mailing_model_real == "hr.applicant": + self.to_email_contact = False + self.to_email_lead = False + self.to_email_partner_ids = False + self.mailing_domain = "[]" + for mass_mailing in self: + mai_data = mass_mailing.sudo()._get_recipients() + email_ids = self.env[self.mailing_model_real].search( + [('id', '=', mai_data)]) + if email_ids: + self.to_email_applicant = email_ids + else: + self.to_email_contact = False + self.to_email_lead = False + self.to_email_applicant = False + self.mailing_domain = "[]" + for mass_mailing in self: + mai_data = mass_mailing.sudo()._get_recipients() + email_ids = self.env[self.mailing_model_real].search( + [('id', '=', mai_data)]) + if email_ids: + self.to_email_partner_ids = email_ids + + @api.onchange('mailing_domain') + def get_mails_recipients(self): + """function used for filtering based on domain filter""" + if self.mailing_model_real == "sale.order" or self.mailing_model_real == "event.registration" or self.mailing_model_real == "event.track": + for mass_mailing in self: + mai_data = mass_mailing.sudo()._get_recipients() + email_ids = self.env[self.mailing_model_real].search( + [('id', '=', mai_data)]) + if email_ids: + self.to_email_partner_ids = email_ids.partner_id + elif self.mailing_model_real == "crm.lead": + for mass_mailing in self: + mai_data = mass_mailing.sudo()._get_recipients() + email_ids = self.env[self.mailing_model_real].search( + [('id', '=', mai_data)]) + if email_ids: + self.to_email_lead = email_ids + elif self.mailing_model_real == "mailing.contact": + for mass_mailing in self: + mai_data = mass_mailing.sudo()._get_recipients() + email_ids = self.env[self.mailing_model_real].search( + [('id', '=', mai_data)]) + if email_ids: + self.to_email_contact = email_ids + elif self.mailing_model_real == "hr.applicant": + for mass_mailing in self: + mai_data = mass_mailing.sudo()._get_recipients() + email_ids = self.env[self.mailing_model_real].search( + [('id', '=', mai_data)]) + if email_ids: + self.to_email_applicant = email_ids + else: + for mass_mailing in self: + mai_data = mass_mailing.sudo()._get_recipients() + email_ids = self.env[self.mailing_model_real].search( + [('id', '=', mai_data)]) + if email_ids: + self.to_email_partner_ids = email_ids + + @api.onchange('to_email_partner_ids', 'to_email_lead', + 'to_email_contact', 'to_email_applicant') + def show_hide_fields(self): + """function is used for Enabling Needed recipient mail + fields by changing check box values.""" + if self.to_email_partner_ids: + self.to_email_partner_check = True + else: + self.to_email_partner_check = False + if self.to_email_lead: + self.to_email_lead_check = True + else: + self.to_email_lead_check = False + if self.to_email_contact: + self.to_email_contact_check = True + else: + self.to_email_contact_check = False + if self.to_email_applicant: + self.to_email_applicant_check = True + else: + self.to_email_applicant_check = False + + def _action_view_documents_filtered(self, view_filter): + """function is used for returning send view in needed recipient tree view""" + if view_filter == 'sent': + res_ids = [] + for mass_mailing in self: + mai_data = mass_mailing.sudo()._get_recipients() + res_ids = self.env[self.mailing_model_real].search( + [('id', '=', mai_data)]) + model_name = self.env['ir.model']._get( + self.mailing_model_real).display_name + return { + 'name': model_name, + 'type': 'ir.actions.act_window', + 'view_mode': 'tree', + 'res_model': self.mailing_model_real, + 'domain': [('id', 'in', res_ids.ids)], + 'context': dict(self._context, create=False) + } + else: + return super(SendGridEmail, self)._action_view_documents_filtered( + view_filter) diff --git a/sendgrid_email/models/model.py b/sendgrid_email/models/model.py deleted file mode 100644 index 449287d74..000000000 --- a/sendgrid_email/models/model.py +++ /dev/null @@ -1,139 +0,0 @@ -# -*- coding: utf-8 -*- -################################################################################### -# -# Cybrosys Technologies Pvt. Ltd. -# -# Copyright (C) 2019-TODAY Cybrosys Technologies (). -# Author: Noushid Khan.P () -# -# This program is free software: you can modify -# it under the terms of the GNU Affero General Public License (AGPL) as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -################################################################################### - -import json - -from odoo import models, fields, _ -import http.client - -from odoo.exceptions import UserError - - -class SendGridSendEmails(models.Model): - _name = "email.api" - _description = "Email Reports" - - name = fields.Char(string="Name") - company_name = fields.Char(string="Company Name") - recipient_name = fields.Char(string="Recipient Name") - to_email = fields.Char(string="Recipient Email ID") - to_email_partner = fields.Many2one("res.partner", string="Recipient Emails") - to_email_partner_check = fields.Boolean() - to_email_lead = fields.Many2one("crm.lead", string="Recipient Emails") - to_email_lead_check = fields.Boolean() - to_email_contact = fields.Many2one("mailing.contact", string="Recipient Emails") - to_email_contact_check = fields.Boolean() - to_email_applicant = fields.Many2one("hr.applicant", string="Recipient Emails") - to_email_applicant_check = fields.Boolean() - from_email = fields.Many2one("email.sent", string="Sender Email") - temp_type = fields.Many2one('email.template', string="Email Template") - temp_id = fields.Char(string="Template_id") - send_date = fields.Datetime(string="Send Date", readonly=True, default=fields.Datetime.now) - error_msg = fields.Text(string="Error Content", readonly=True) - error_check = fields.Boolean() - state = fields.Selection([('send', "Send"), ('error', "Error")], readonly=True, string="State", default='send') - bounce_msg = fields.Text(string="Bounce Message") - email_finder = fields.Integer(string="Email finder") - - def bounce_check(self): - """ - function is used for Checking Email Bounce - Status. - - """ - - conn = http.client.HTTPSConnection("api.sendgrid.com") - - payload = "{}" - - headers = {'authorization': "Bearer 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"} - - conn.request("GET", "/v3/suppression/bounces/" + self.to_email + "", payload, headers) - - res = conn.getresponse() - print("res", res) - data = res.read() - print("data1", data) - bounce_msg = json.loads(data.decode("utf-8")) - if bounce_msg: - self.bounce_msg = bounce_msg[0]['reason'] - - else: - self.bounce_msg = "This Email Is Not Bounced" - - def send_error_mails(self): - """ - function is used for Resending Error State - mails. - - """ - company_id = self.env.company - api_key = "" - for line in self: - if line.state == 'error': - if not line.temp_id: - raise UserError(_("It Needs A Template ID")) - if line.from_email: - from_email = line.from_email.email_id - else: - from_email = "noreply@johndoe.com" - api_info = self.env['ir.config_parameter'].search( - [('key', '=', "SendGrid API Key " + company_id.name + "")]) - if not api_info: - raise UserError(_("It Needs API Key")) - if api_info.company_id.id == self.env.company.id: - api_key = api_info.value - if not api_key and api_key == "": - raise UserError(_("Your Company Needs an API Key")) - conn = http.client.HTTPSConnection("api.sendgrid.com") - to_company = line.company_name - if not to_company: - to_company = "" - temp_id = line.temp_id - payload = "" - if line.to_email and line.recipient_name: - payload = "{\"personalizations\":[{\"to\":[{\"email\":\"" + line.to_email + "\"}],\"dynamic_template_data\":{\"firstname\":\"" + line.recipient_name + "\",\"english\":\"true\",\"company\":\"" + to_company + "\"},\"subject\":\"Official Mail\"}],\"from\":{\"email\":\"" + from_email + "\",},\"template_id\":\"" + temp_id + "\"}" - headers = { - 'authorization': "Bearer " + api_key + "", - 'content-type': "application/json" - } - - conn.request("POST", "/v3/mail/send", payload, headers) - - res = conn.getresponse() - - data_msg = res.read() - - if data_msg.decode("utf-8"): - error_data = json.loads(data_msg.decode("utf-8")) - line.error_msg = error_data['errors'][0]['message'] - if not data_msg.decode("utf-8"): - line.state = 'send' - line.error_msg = "" - line.error_check = False - email_id_use = self.env['mailing.mailing'].search([('id', '=', line.email_finder)]) - email_id_use.send_grid_check = True - email_id_use.sent_count += 1 - email_id_use.write({ - 'state': 'done' - }) diff --git a/sendgrid_email/models/res_config_settings.py b/sendgrid_email/models/res_config_settings.py index d0d5a3b54..1e1e7dd27 100644 --- a/sendgrid_email/models/res_config_settings.py +++ b/sendgrid_email/models/res_config_settings.py @@ -21,19 +21,14 @@ # ################################################################################### -from odoo import models, fields, api, _ +from odoo import models, fields -class SendGridApiConfig(models.TransientModel): +class ResConfigSettings(models.TransientModel): + """Inherits the model res.config.settings to add extra fields""" _inherit = 'res.config.settings' - send_grid_api_check = fields.Boolean(string="SendGrid API") - send_grid_api_value = fields.Char(string='API key') - - def set_values(self): - """ save values in the settings fields """ - - super(SendGridApiConfig, self).set_values() - company_id = self.env.company - self.env['ir.config_parameter'].sudo().set_param("SendGrid API Key "+company_id.name+"", - self.send_grid_api_value) + send_grid_api_check = fields.Boolean(string="SendGrid API", + config_parameter="sendgrid_email.send_grid_api_check") + send_grid_api_value = fields.Char(string='API key', + config_parameter="sendgrid_email.send_grid_api_value") diff --git a/sendgrid_email/models/email_send.py b/sendgrid_email/models/sendgrid_email_template.py similarity index 64% rename from sendgrid_email/models/email_send.py rename to sendgrid_email/models/sendgrid_email_template.py index 6941a4d86..2373d995a 100644 --- a/sendgrid_email/models/email_send.py +++ b/sendgrid_email/models/sendgrid_email_template.py @@ -20,13 +20,18 @@ # along with this program. If not, see . # ################################################################################### - from odoo import models, fields -class EmailDetails(models.Model): - _name = "email.sent" - _description = 'Email From Mails' +class SendgridEmailTemplate(models.Model): + """Creates the model sendgrid.email.template to create the email templates + that needs to be sent through the send grid""" + _name = "sendgrid.email.template" + _rec_name = "temp_name" + _description = "Sendgrid Email Template" - name = fields.Char(string="Name", required=True) - email_id = fields.Char(string="Email ID", required=True) + temp_name = fields.Char(string="Template Name", required=True) + ver_subject = fields.Char(string="Template Subject", required=True) + temp_cont = fields.Html(string="Template Content", + help="content convert to html code", translate=True, + sanitize=False) \ No newline at end of file diff --git a/sendgrid_email/security/ir.model.access.csv b/sendgrid_email/security/ir.model.access.csv index 98bc69cf3..d52abfc5e 100644 --- a/sendgrid_email/security/ir.model.access.csv +++ b/sendgrid_email/security/ir.model.access.csv @@ -1,4 +1,3 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_sendgrid_email_template_admin,access.sendgrid.email.template.admin,model_sendgrid_email_template,base.group_system,1,1,1,1 access_email_api,access.email.api,model_email_api,base.group_system,1,1,1,1 -access_email_sent,access.email.sent,model_email_sent,base.group_system,1,1,1,1 -access_email_template,access.email.template,model_email_template,base.group_system,1,1,1,1 \ No newline at end of file diff --git a/sendgrid_email/static/description/assets/screenshots/14.png b/sendgrid_email/static/description/assets/screenshots/14.png new file mode 100644 index 000000000..a73b187b5 Binary files /dev/null and b/sendgrid_email/static/description/assets/screenshots/14.png differ diff --git a/sendgrid_email/static/description/assets/screenshots/3.png b/sendgrid_email/static/description/assets/screenshots/3.png new file mode 100644 index 000000000..8eefa8f29 Binary files /dev/null and b/sendgrid_email/static/description/assets/screenshots/3.png differ diff --git a/sendgrid_email/static/description/assets/screenshots/4.png b/sendgrid_email/static/description/assets/screenshots/4.png new file mode 100644 index 000000000..4ffe016a8 Binary files /dev/null and b/sendgrid_email/static/description/assets/screenshots/4.png differ diff --git a/sendgrid_email/static/description/assets/screenshots/5.png b/sendgrid_email/static/description/assets/screenshots/5.png new file mode 100644 index 000000000..07837e11a Binary files /dev/null and b/sendgrid_email/static/description/assets/screenshots/5.png differ diff --git a/sendgrid_email/static/description/assets/screenshots/6.png b/sendgrid_email/static/description/assets/screenshots/6.png new file mode 100644 index 000000000..4204bd239 Binary files /dev/null and b/sendgrid_email/static/description/assets/screenshots/6.png differ diff --git a/sendgrid_email/static/description/index.html b/sendgrid_email/static/description/index.html index e4181eb1c..effb43769 100644 --- a/sendgrid_email/static/description/index.html +++ b/sendgrid_email/static/description/index.html @@ -15,7 +15,6 @@ style="background-color: #875A7B !important; color: #fff !important; font-weight: 600 !important; padding: 5px 15px 8px !important; margin: 0 5px !important;"> Enterprise - @@ -337,7 +336,7 @@ In Email Marketing Configuration have a checkbox field SendGrid API by checking style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> In Email Marketing Configuration have a sub menu SendGrid Template Details

- @@ -350,7 +349,7 @@ In Email Marketing Configuration have a checkbox field SendGrid API by checking style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> In Email Template Details show a tree view like below create new template by clicking Create button

- @@ -363,7 +362,7 @@ In Email Marketing Configuration have a checkbox field SendGrid API by checking style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> Email template form view is shown in below here you can fill all the fields. You can fill the Email subject and content in the subject field and content box and click the save button.

- @@ -376,30 +375,7 @@ In Email Marketing Configuration have a checkbox field SendGrid API by checking style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> This Form view will be fill like below.

- - - -
-

- Template create button

-

- Template create button in using for creating the template. -

- -
- -
-

Create Version button

-

- After clicking template create button Template ID will be fill. Using Template ID We can Write the template content by clicking Create Version button. -

-
@@ -481,18 +457,6 @@ In Email Marketing Configuration have a checkbox field SendGrid API by checking width="100%" height="auto" /> -
-

- Draft State to Send State

-

- If the mail send to the recipient then the draft state is change to send state. User can see which recipient have send the mails in sent smart button on the mailing form -

- -
-

@@ -505,18 +469,6 @@ In Email Marketing Configuration have a checkbox field SendGrid API by checking width="100%" height="auto" />

-
-

- Recipient Details

-

- By clicking Send smart button it will show a tree view like below, here we can see mailing completed recipient details. -

- -
-

@@ -525,7 +477,7 @@ In Email Marketing Configuration have a checkbox field SendGrid API by checking style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> In Email Marketing Reporting menu have sub menu SendGrid Send Emails, Here user can get the mailing details done by SendGrid Service.

-

@@ -588,36 +540,8 @@ In Email Marketing Configuration have a checkbox field SendGrid API by checking - - -
-

- Storing from Email Records

-

Mailing configuration menu have submenu SendGrid From Email it used form storing from email Records. User can use this from emails on mailing page. -

- -
-
-

- Create New

-

- User can create new from email record by clicking on create button on the view. -

- -
- - - - -
+ + + + Send Emails Tree + email.api + + + + + + + + + + + Send Emails Form + email.api + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
\ No newline at end of file diff --git a/sendgrid_email/views/mailing_mailing_views.xml b/sendgrid_email/views/mailing_mailing_views.xml new file mode 100644 index 000000000..f7a097b21 --- /dev/null +++ b/sendgrid_email/views/mailing_mailing_views.xml @@ -0,0 +1,50 @@ + + + + + SendGrid Mass MAil + mailing.mailing + + + +