|
| 1 | +import smtplib |
| 2 | +import ssl |
| 3 | +from socket import gaierror |
| 4 | + |
| 5 | +from odoo import _, fields, models |
| 6 | +from odoo.exceptions import UserError |
| 7 | + |
| 8 | + |
| 9 | +class MailServerTestWizard(models.TransientModel): |
| 10 | + _name = "mail.server.test.wizard" |
| 11 | + _description = "Wizard de prueba de servidor de correo saliente" |
| 12 | + |
| 13 | + # Stored as Integer to reliably reference servers that may be archived |
| 14 | + # (neutralized databases deactivate all ir.mail_server records). |
| 15 | + mail_server_id = fields.Integer( |
| 16 | + string="ID del servidor de correo saliente", |
| 17 | + required=True, |
| 18 | + ) |
| 19 | + email_to = fields.Char( |
| 20 | + string="Correo destinatario", |
| 21 | + required=True, |
| 22 | + ) |
| 23 | + |
| 24 | + def action_send_test_mail(self): |
| 25 | + """Build and send a test email directly via SMTP, bypassing all |
| 26 | + Python-level sending guards (server_mode, mail neutralization, etc.). |
| 27 | +
|
| 28 | + The bypass is achieved by calling ``ir.mail_server.connect()`` with |
| 29 | + ``allow_archived=True`` and then invoking ``smtp.send_message()`` |
| 30 | + directly — never going through ``send_email()``, which is the layer |
| 31 | + where restrictions such as ``server_mode.allow_send_mail`` operate. |
| 32 | + """ |
| 33 | + self.ensure_one() |
| 34 | + IrMailServer = self.env["ir.mail_server"] |
| 35 | + |
| 36 | + # Browse with active_test=False so archived servers (neutralized DBs) |
| 37 | + # are accessible. |
| 38 | + mail_server = IrMailServer.sudo().with_context(active_test=False).browse(self.mail_server_id) |
| 39 | + if not mail_server._ids: |
| 40 | + raise UserError( |
| 41 | + _("No se encontró el servidor de correo. " "Por favor, recargue la página e intente de nuevo.") |
| 42 | + ) |
| 43 | + |
| 44 | + email_from = mail_server._get_test_email_from() |
| 45 | + message = IrMailServer.build_email( |
| 46 | + email_from=email_from, |
| 47 | + email_to=[self.email_to], |
| 48 | + subject=_("Prueba de mail desde Odoo"), |
| 49 | + body=_("Mail de prueba enviado desde mi base de Odoo. " "Por favor no responder."), |
| 50 | + subtype="plain", |
| 51 | + ) |
| 52 | + |
| 53 | + smtp = None |
| 54 | + try: |
| 55 | + # allow_archived=True is critical for neutralized databases where |
| 56 | + # all real servers are deactivated by the neutralize process. |
| 57 | + smtp = IrMailServer.connect( |
| 58 | + mail_server_id=mail_server.id, |
| 59 | + allow_archived=True, |
| 60 | + ) |
| 61 | + if smtp: |
| 62 | + smtp.send_message(message) |
| 63 | + except (gaierror, TimeoutError) as e: |
| 64 | + raise UserError( |
| 65 | + _( |
| 66 | + "No se pudo enviar el mail: Sin respuesta del servidor. " "Verifique la dirección y el puerto.\n%s", |
| 67 | + e, |
| 68 | + ) |
| 69 | + ) from e |
| 70 | + except smtplib.SMTPRecipientsRefused as e: |
| 71 | + raise UserError( |
| 72 | + _( |
| 73 | + "No se pudo enviar el mail: El servidor rechazó la dirección destinataria.\n%s", |
| 74 | + e, |
| 75 | + ) |
| 76 | + ) from e |
| 77 | + except smtplib.SMTPException as e: |
| 78 | + raise UserError(_("No se pudo enviar el mail: %s", e)) from e |
| 79 | + except ssl.SSLError as e: |
| 80 | + raise UserError(_("No se pudo enviar el mail: Error de SSL.\n%s", e)) from e |
| 81 | + except Exception as e: |
| 82 | + raise UserError(_("No se pudo enviar el mail: %s", e)) from e |
| 83 | + finally: |
| 84 | + if smtp: |
| 85 | + try: |
| 86 | + smtp.quit() |
| 87 | + except Exception: |
| 88 | + pass |
| 89 | + |
| 90 | + return { |
| 91 | + "type": "ir.actions.client", |
| 92 | + "tag": "display_notification", |
| 93 | + "params": { |
| 94 | + "message": _("¡Mail de prueba enviado con éxito! " "Por favor, revise su casilla de correo."), |
| 95 | + "type": "success", |
| 96 | + "sticky": False, |
| 97 | + "next": {"type": "ir.actions.act_window_close"}, |
| 98 | + }, |
| 99 | + } |
0 commit comments