TypeError: 无法设置未定义的属性(设置 ‘mailer’)

huangapple go评论113阅读模式
英文:

TypeError: Cannot set properties of undefined (setting 'mailer')

问题

我正在尝试使用 nodemon(^2.0.22) 和 nodemailer(^6.9.3) 设置发送邮件。

原来,在尝试发送电子邮件时遇到此错误: "TypeError: Cannot set properties of undefined (setting 'mailer')",位于 nodemailer 库的 index.js 的第 45 行。访问此行时,我们有以下代码: this.transporter.mailer = this;

我无法确定是什么原因导致了这个错误。

谢谢。

英文:

I'm trying to set up an email sending using nodemon(^2.0.22) and nodemailer(^6.9.3).

It turns out that when trying to send the email I come across this error: "TypeError: Cannot set properties of undefined (setting 'mailer')" On line 45 of index.js of the nodemailer lib. When accessing this line, we have the following code: this.transporter.mailer = this;

I cannot identify what is causing this error. I'm going to pass here the HTML of my form, the header of my index.js and the route that sends the emails, so that you can help me.

Thanks.

HTML

  1. <div id="tab2Content" class="tab-content">
  2. <form id="formulario" action="/send" method="POST" role="form" enctype="Content-Type">
  3. <div class="row">
  4. <div>
  5. <h2>Dados do solicitante</h2>
  6. </div>
  7. <div class="radio-container">
  8. <label for="sigSim">Desejo não me identificar</label> <input type="radio" name="sigilo" id="sigSim" value="com_sigilo" required="" onchange="ocultarDivs()"> <br>
  9. </div>
  10. <div class="radio-container">
  11. <label id="lblMaior" for="sigNao">Desejo me identificar, mostrando os meus dados</label> <input type="radio" name="sigilo" id="sigNao" value="sem_sigilo" required="" checked onchange="ocultarDivs()">
  12. </div>
  13. <br>
  14. <br>
  15. <fieldset id="dados_user">
  16. <hr class="col-md-7 form-group mt-3 mt-md-0">
  17. <div class="col-md-6 form-group">
  18. <label for="name">Nome: </label>
  19. <input type="text" name="name" class="form-control" id="name" placeholder="" >
  20. </div>
  21. <div class="col-md-6 form-group mt-3 mt-md-0">
  22. <label for="email">E-mail: </label>
  23. <input type="email" class="form-control" name="email" id="email" placeholder="" >
  24. </div>
  25. <div class="col-md-6 form-group mt-3 mt-md-0">
  26. <label for="cep">CEP: </label>
  27. <input type="text" class="form-control" name="cep" id="cep" value="" size="10" maxlength="9" onblur="pesquisacep(this.value);" placeholder="Digite apenas números" >
  28. </div>
  29. <div class="col-md-6 form-group mt-3 mt-md-0" id="rua_num">
  30. <div id="div_ende" class="col-md-10">
  31. <label for="endereco">Rua: </label>
  32. <input type="text" class="form-control " name="endereco" id="rua" placeholder="" >
  33. </div>
  34. <div >
  35. <label for="numero">N°: </label>
  36. <input type="text" class="form-control " name="numero" id="numero" placeholder="" >
  37. </div>
  38. </div>
  39. <div class="col-md-6 form-group mt-3 mt-md-0">
  40. <label for="complemento">Complemento: </label>
  41. <input type="text" class="form-control " name="complemento" id="complemento" placeholder="" >
  42. </div>
  43. <div class="col-md-6 form-group mt-3 mt-md-0">
  44. <label for="bairro">Bairro: </label>
  45. <input type="text" class="form-control" name="bairro" id="bairro" placeholder="" >
  46. </div>
  47. <div class="col-md-6 form-group mt-3 mt-md-0">
  48. <label for="cidade">Cidade: </label>
  49. <input type="text" class="form-control" name="cidade" id="cidade" placeholder="" >
  50. </div>
  51. <div class="col-md-6 form-group mt-3 mt-md-0">
  52. <label for="uf">Estado: </label>
  53. <input type="text" class="form-control" name="uf" id="uf" placeholder="" >
  54. </div>
  55. <!-- <div class="col-md-6 form-group mt-3 mt-md-0">
  56. <label for="fixo">Telefone Fixo: </label>
  57. <input type="tel" class="form-control" name="fixo" id="fixo" placeholder="" required="false">
  58. </div> -->
  59. <div class="col-md-6 form-group mt-3 mt-md-0">
  60. <label for="celular">Telefone Celular: </label>
  61. <input type="tel" class="form-control" name="celular" id="celular" placeholder="" >
  62. </div>
  63. </fieldset>
  64. </div>
  65. <br>
  66. <hr class="col-md-7 form-group mt-3 mt-md-0">
  67. <div class="form-group mt-6">
  68. <div>
  69. <h2>Dados da solicitação</h2>
  70. </div>
  71. <div class="col-md-7 form-group mt-3 mt-md-0">
  72. <!-- alterar esse campo para lista de categoria: Solicitação, Elogio, Sugestão, Reclamação e Denúncia -->
  73. <label for="categoria">Categoria: </label>
  74. <select name="categoria" id="categoria" class="form-select-sm">
  75. <option value="" disabled selected>Selecione uma categoria...</option>
  76. <option value="Solicitação">Solicitação</option>
  77. <option value="Reclamacao">Reclamação</option>
  78. <option value="Denúncia">Denúncia</option>
  79. <option value="Outros">Outros</option>
  80. </select>
  81. </div>
  82. <br>
  83. <fieldset id="dados_user">
  84. <div class="col-md-7 form-group mt-3 mt-md-0" >
  85. <label for="resposta" id="lblresposta">Como deseja receber a resposta: </label>
  86. <!-- alterar esse campo para lista de como deseja receber a resposta: e-mail, carta, oficio, presencial, whatsapp, sem resposta -->
  87. <select name="resposta" id="resposta" class="form-select-sm">
  88. <option value="" disabled selected>Selecione uma resposta...</option>
  89. <option value="E-mail">E-mail</option>
  90. <option value="Ligação">Ligação</option>
  91. <option value="Presencial">Presencial</option>
  92. <option value="Whatsapp">Whatsapp</option>
  93. <option value="Sem resposta">Sem Resposta</option>
  94. </select>
  95. </div>
  96. </fieldset>
  97. </div>
  98. <br>
  99. <hr class="col-md-7 form-group mt-3 mt-md-0">
  100. <div class="form-group mt-3">
  101. <div>
  102. <h2>Mensagem</h2>
  103. </div>
  104. <div class="col-md-7 form-group mt-3 mt-md-0">
  105. <label for="assunto">Assunto: </label>
  106. <input type="text" class="form-control" name="assunto" id="assunto" placeholder="" required="">
  107. </div>
  108. <div class="col-md-7 form-group mt-3 mt-md-0">
  109. <label for="arquivo">Arquivo: </label>
  110. <input type="file" multiple accept=".jpg,.png,.jpeg,.bitmap,.doc,.docx,.pdf,.xls,.xlsx" class="form-control" name="arquivo" id="arquivo" placeholder="" >
  111. </div>
  112. <div class="col-md-7 form-group mt-3 mt-md-0">
  113. <label for="mensagem">Mensagem: </label>
  114. <textarea class="form-control" name="mensagem" id="mensagem" rows="7" placeholder="" required=""></textarea>
  115. </div>
  116. </div>
  117. <br>
  118. <input type="checkbox" id="lgpdCheckbox" name="lgpdCheckbox">
  119. <label for="lgpdCheckbox">Li e concordo com os <a href="#" data-bs-toggle="modal" data-bs-target="#pdfModal">termos de consentimento da LGPD</a></label>
  120. <br>
  121. <br>
  122. <div class="col-md-7 form-group mt-3 mt-md-0 text-center"><button id="enviar" name="btn_ouvidoria" value="ouvidoria" type="submit">Enviar mensagem</button></div>
  123. </form>
  124. </div>

the header of my index.js

  1. // Importa o módulo express para esse arquivo
  2. const express = require("express");
  3. const { JSDOM } = require('jsdom');
  4. const { url } = require("inspector");
  5. const nodemailer = require('nodemailer')
  6. const path = require("path");
  7. const multer = require("multer")
  8. const fs = require('fs');
  9. const Swal = require('sweetalert2');
  10. const ejs = require("ejs");
  11. require("dotenv").config();
  12. const FileType = require('file-type');
  13. // Instancia uma referência do express no projeto
  14. const app = express();
  15. const bodyParser = require('body-parser');
  16. const port = process.env.PORT || 5150; // Const para armanezar a porta do servidor
  17. app.set("view engine", "ejs");
  18. app.set('views', path.join(__dirname, 'views'));
  19. const SMTPTransport = require("nodemailer/lib/smtp-transport");
  20. app.use(express.urlencoded());
  21. app.use(bodyParser.urlencoded({ extended: true }));
  22. app.use(bodyParser.json());
  23. const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>');
  24. const doc = dom.window.document;
  25. const smtp = process.env.SMTP
  26. const user_O = process.env.EMAIL_OUVIDORIA
  27. const user_C = process.env.EMAIL_CONTATO
  28. const pass = process.env.SENHA
  29. const porta = process.env.PORTA

Route of send e-mail

  1. app.post("/send", (req, res) =>{
  2. app.use((err, req, res, next) => {
  3. console.error(err);
  4. res.status(500).send('Erro interno do servidor');
  5. });
  6. function procurarValor(x, lista) {
  7. if (lista.includes(x)) {
  8. return "Encontrado";
  9. } else {
  10. return "Não encontrado";
  11. }
  12. }
  13. console.log('inicio do codigo')
  14. const{name, email, cep, endereco, numero, complemento, bairro, cidade, uf, celular, categoria, resposta, assunto, mensagem} = req.body;
  15. const btn = req.body.btn_ouvidoria;
  16. console.log(req.body)
  17. let recebedor = ""
  18. let permissao = ""
  19. let remetente = ""
  20. console.log(user_O)
  21. console.log(pass)
  22. if (btn == "ouvidoria"){
  23. console.log('acessou o if do btn ouvidoria')
  24. recebedor = "ouvidoria@ezco.com.br";
  25. permissao = req.body.sigilo;
  26. const transporter = nodemailer.createTransport(
  27. console.log('acessou a criação do transporter'),
  28. new SMTPTransport({
  29. host: smtp,
  30. port: Number(porta),
  31. auth: JSON.stringify({user: user_O, pass: pass})
  32. }));
  33. console.log('saiu do transporter');
  34. console.log(transporter.host, transporter.port, transporter.user, transporter.pass, transporter.auth, transporter.secure)
  35. transporter.verify(function(error, success) {
  36. if (error) {
  37. console.log('Erro na conexão SSL/TLS:', error);
  38. } else {
  39. console.log('Conexão SSL/TLS estabelecida com sucesso');
  40. }
  41. });
  42. console.log('Final do id do btn ouvidoria')
  43. // remetente = user_O;
  44. } else if (btn === "fale_conosco"){
  45. recebedor = "contato@ezco.com.br";
  46. permissao = req.body.sigilo2;
  47. const transporter = nodemailer.createTransport( new SMTPTransport({
  48. host: smtp,
  49. port: Number(465),
  50. user: process.env.EMAIL_CONTATO,
  51. pass: process.env.SENHA,
  52. auth: {user, pass},
  53. secure: true
  54. }));
  55. transporter.verify(function(error, success) {
  56. if (error) {
  57. console.log('Erro na conexão SSL/TLS:', error);
  58. } else {
  59. console.log('Conexão SSL/TLS estabelecida com sucesso');
  60. }
  61. });
  62. // remetente = user_C;
  63. }
  64. console.log('começo da lista de cidades')
  65. let cidades = [
  66. 'Abatiá',
  67. 'Andirá',
  68. 'Bandeirantes',
  69. 'Barra do Jacaré',
  70. 'Cambará',
  71. 'Carlópolis',
  72. 'Congonhinhas',
  73. 'Conselheiro Mairinck',
  74. 'Cornélio Procópio',
  75. 'Figueira',
  76. 'Guapirama',
  77. 'Ibaiti',
  78. 'Itambaracá',
  79. 'Jaboti',
  80. 'Jacarezinho',
  81. 'Japira',
  82. 'Joaquim Távora',
  83. 'Jundiaí do Sul',
  84. 'Leópolis',
  85. 'Nova América da Colina',
  86. 'Nova Fátima',
  87. 'Nova Santa Bárbara',
  88. 'Pinhalão',
  89. 'Quatiguá',
  90. 'Rancho Alegre',
  91. 'Ribeirão Claro',
  92. 'Ribeirão do Pinhal',
  93. 'Salto do Itararé',
  94. 'Santa Amélia',
  95. 'Santa Cecília do Pavão',
  96. 'Santa Mariana',
  97. 'Santana do Itararé',
  98. 'Santo Antônio da Platina',
  99. 'Santo Antônio do Paraíso',
  100. 'São Jerônimo da Serra',
  101. 'São José da Boa Vista',
  102. 'São Sebastião da Amoreira',
  103. 'Sapopema',
  104. 'Sertaneja',
  105. 'Siqueira Campos',
  106. 'Tomazina',
  107. 'Uraí',
  108. 'Wenceslau Braz'
  109. ]
  110. console.log('final da lista de cidades')
  111. // const anexo = req.files.map((arquivo) => ({
  112. // filename: arquivo.originalname,
  113. // path: arquivo.path,
  114. // }));
  115. // const totalSize = req.files.reduce((sum, file) => sum + file.size, 0);
  116. // const limiteTamanho = 20 * 1024 * 1024; // 20MB
  117. // Verifica se a soma dos tamanhos excede o limite
  118. // if (totalSize > limiteTamanho) {
  119. // Lidar com o limite excedido
  120. // var exibirAlerta = true;
  121. // res.render('ouvidoria', { exibirAlerta: exibirAlerta });
  122. //apaga os arquivos que foram carregados
  123. // req.files.forEach(arquivo => {
  124. // fs.unlink(arquivo.path, (error) => {
  125. // if (error) {
  126. // console.error('Erro ao excluir o arquivo:', error);
  127. // } else {
  128. // console.log('Arquivo excluído com sucesso.');
  129. // }
  130. // });
  131. // });
  132. // return; // Encerra a função para evitar o envio do e-mail
  133. // }
  134. if (permissao == "com_sigilo" || permissao == "com_sigilo2"){
  135. console.log('inicio do codigo com sigilo')
  136. transporter.sendMail({
  137. from: remetente,
  138. to: recebedor,
  139. subject: `${categoria}: ${assunto}`,
  140. text:
  141. `Mensagem: ${mensagem}`
  142. // attachments: anexo,
  143. }).then(info =>{
  144. console.log('inicio do codigo then de envio')
  145. // req.files.forEach(arquivo => {
  146. // fs.unlink(arquivo.path, (error) => {
  147. // if (error) {
  148. // console.error('Erro ao excluir o arquivo:', error);
  149. // } else {
  150. // console.log('Arquivo excluído com sucesso.');
  151. // }
  152. // });
  153. // });
  154. res.render("confirmacao_sem_resp")
  155. }).catch(error =>{
  156. console.log('inicio do codigo catch de envio')
  157. // req.files.forEach(arquivo => {
  158. // fs.unlink(arquivo.path, (error) => {
  159. // if (error) {
  160. // console.error('Erro ao excluir o arquivo:', error);
  161. // } else {
  162. // console.log('Arquivo excluído com sucesso.');
  163. // }
  164. // });
  165. // });
  166. // res.send(error)
  167. res.render("confirmacao_erro")
  168. })
  169. }else if (permissao == "sem_sigilo" || permissao == "sem_sigilo2"){
  170. let resultado = procurarValor(`${cidade}`, cidades);
  171. let regiao = ""
  172. if (resultado = "Encontrado"){
  173. regiao = "Norte Pioneiro"
  174. }else{
  175. regiao = "Sem região"
  176. }
  177. transporter.sendMail({
  178. from: remetente,
  179. to: recebedor,
  180. replyTo: email,
  181. subject: `${regiao} - ${categoria}: ${assunto}`,
  182. text:
  183. `Nome: ${name}
  184. E-mail de contato: ${email}
  185. CEP: ${cep}
  186. Endereço: ${endereco}, ${numero} - ${complemento} - ${bairro} - ${cidade} - ${uf}
  187. Telefone celular: ${celular}
  188. Prefere que seja respondido via: ${resposta}
  189. Mensagem: ${mensagem}`
  190. // attachments: anexo,
  191. }).then(info =>{
  192. // req.files.forEach(arquivo => {
  193. // fs.unlink(arquivo.path, (error) => {
  194. // if (error) {
  195. // console.error('Erro ao excluir o arquivo:', error);
  196. // } else {
  197. // console.log('Arquivo excluído com sucesso.');
  198. // }
  199. // });
  200. // });
  201. res.render("confirmacao_com_resp")
  202. }).catch(error =>{
  203. // req.files.forEach(arquivo => {
  204. // fs.unlink(arquivo.path, (error) => {
  205. // if (error) {
  206. // console.error('Erro ao excluir o arquivo:', error);
  207. // } else {
  208. // console.log('Arquivo excluído com sucesso.');
  209. // }
  210. // });
  211. // });
  212. res.render("confirmacao_erro")
  213. })
  214. }
  215. });

I've already searched the internet, in several places, including ChatGPT for the reason for this problem. Most of them point me to credential errors, however the credentials are set and checked.

答案1

得分: 2

我认为问题出在nodemailer.createTransport()的语法上。根据文档,无需将新的SMTPTransport作为参数传递。
预期的语法应该像这样:

  1. nodemailer.createTransport({
  2. pool: true,
  3. host: "smtp.example.com",
  4. port: 465,
  5. secure: true, // 使用TLS
  6. auth: {
  7. user: "username",
  8. pass: "password",
  9. },
  10. });

由于未能获取传输器,值将返回为undefined,因此this.transporter.mailer = this;将会中断,因为undefined没有"mailer"属性。

英文:

I think the problem is in the syntax of nodemailer.createTransport(). According to the documentation, there is no need to pass new SMTPTransport as an argument.
<br />
The expected syntax should look like this:

  1. nodemailer.createTransport({
  2. pool: true,
  3. host: &quot;smtp.example.com&quot;,
  4. port: 465,
  5. secure: true, // use TLS
  6. auth: {
  7. user: &quot;username&quot;,
  8. pass: &quot;password&quot;,
  9. },
  10. });

By failing to retrieve a transporter, the values returns as undefined, and this.transporter.mailer = this; will break because undefined has no "mailer" attribute.

huangapple
  • 本文由 发表于 2023年7月3日 21:07:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76605041.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定