Quem tiver problema no teste aos 21:00. colocar esse código aqui no arquivo mailer.js transport.use('compile', hbs({ viewEngine: { defaultLayout: undefined, partialsDir: path.resolve('./src/resources/mail/') }, viewPath: path.resolve('./src/resources/mail/'), extName: '.html', })); Abraço!
Na realidade, no 'const handlebarOptions, é só deixar o defaultLayout em defaultLayout: null; Aí caso você queira usar outros layouts, não vai setar sempre no de forgot_password.
Pra quem teve problema em 15:04 com deprecated await User.findByIdAndUpdate(user.id, { '$set': { { passwordResetToken: token, passwordResetExpires: now } } }); A solução que eu achei await User.updateOne( { _id: user.id }, { passwordResetToken: token, passwordResetExpires: now }, ); Tbm tive problema no Mailer por que ele pedi um caminho para importar um template(Eu li mais sobre isso. Porém não tenho certeza se o que eu fiz é a melhor solução). Então eu coloquei os parametros para caso queira colocar o template mas o desativei so para testar a aplicação sem precisar de um. transport.use( 'compile', hbs({ viewEngine: { extName: '.hbs', partialsDir: path.resolve('resources', 'templates'), defaultLayout: false, }, viewPath: path.resolve('resources', 'mail'), extName: '.html', }), ); O resultado é o mesmo. Espero ter ajudado
É só comigo que dá uma sensação de estranheza ver a lógica de negócio dentro das rotas? Fora isso, o conteúdo é muito bom. Vlw Diego por disponibilizar estes conteúdos, está sendo muito bom para os meus estudos com NodeJS.
@@matheusmgp1 mais didático que deixar organizado as rotas e levar as regras pro controller? Acho que não tô bem então, porque pensa num ser que ficou confuso pra caralho, principalmente vindo do Laravel: eu.
Aula sensacional!! para quem está com o erro "A partials dir must be a string or config object." mudei uma parte do "modules/mailer.js" para: transport.use('compile', hbs({ viewEngine: { layoutsDir: path.resolve('./src/resources/mail/'), partialsDir: path.resolve('./src/resources/mail/'), }, viewPath: path.resolve('./src/resources/mail/'), extName: '.html', })); e criei o arquivo "main.handlebars" no caminho "resources/mail", com o seguinte código:
My Awesome App
{{{body}}}
Quando enviar o email, ele vai substituir o "{{{body}}}" pelo conteúdo do arquivo "forgot_password.html" ;)
UHUUU!! Muito bom o conteúdo, existem algumas diferenças com relação ao nodemailer-express-handlebars, na última versão para configuração do viewEngine, ou pelo menos eu configurei de forma diferente para conseguir funcionar. Coloquei assim: transport.use('compile', hbs({ viewEngine: { extname: '.html', layoutsDir: 'src/resources/mail/', defaultLayout: 'forgot_password', partialsDir: 'src/resources/mail/', }, viewPath: 'src/resources/mail/', extName: '.html' }));
Mais uma vez, tenho que parabenizar pelo trabalho, muito bem feito. Fazem toda a diferença para quem está iniciando, incentivando cada vez mais novos desenvolvedores a seguirem no caminho, e empreendendo cada vez mais.
Tooooop meu velho! Uma das melhores series que eu já vi aqui no youtube, parabéns mesmo cara! Vou acompanhar até o final da serie e logo depois vou começar a de react
para quem estiver tendo problemas com o envio de email aos 21:00: const transport = nodemailer.createTransport({ host, port, auth: { user, pass: password //alterar o nome da chave para ''pass'', passando o valor de password } })
Pra quem tiver tendo esse problema de diretorio => [Error: ENOENT: no such file or directory, open 'D:\projetos ode\server_rocket\src\src esources\mail\auth\forgot_password.html'] { errno: -4058, code: 'ENOENT', syscall: 'open', path: 'D:\\projetos\ ode\\server_rocket\\src\\src\ esources\\mail\\auth\\forgot_password.html' } Eu consegui resolver assim, e agora está sendo enviado com sucesso o email com token. transport.use( "compile", hbs({ viewEngine: { defaultLayout: undefined, partialsDir: path.resolve("../src/resources/mail/"), }, viewPath: path.resolve("../src/resources/mail/"), extName: ".html", }) );
Sim, isso mesmo tenho muita dificuldade nisso em trazer a informação correspondente de cada usuários, onde cada um possui um nível permissão, podendo acessar somente algumas páginas ou executar determinadas funções. Espero que tenha isso no curso para ser 1000. Mas já está de parabéns pelas aulas disponibilizadas.
Fala Diego, to gostando demais dessa série. Apesar de ja trabalhar com isso, algumas coisas que voce esta ensinando resolvem alguns problemas que por vezes surgiram comigo. Mas eu gostaria de ver como ficaria melhor essa organização de controllers e rotas, uma forma de modularizar mais, separando-os e talz. Fica como sugestão. E parabéns pelo conteúdo man!
Em breve melhorarei ainda mais essa estrutura, estamos indo a cada aula entendendo o que está se tornando repetitivo e verboso para resolver cada item no seu tempo. A separação de rotas é muito legal e provavelmente teremos nos próximos vídeos. Valeu Italo.
Eu gostaria de ver série sobre ACL,NOSQL com mongo, onde o admin possa ver menus que o usuário comum não pode,o admin pode controlar regras que o o user normal não pode.Admin controla o que os níveis de users podem ou não ver e fazer. Usando apis públicas e privadas de terceiros, para servir dados para o usuário e para o admin.Criar uma regra de negócio para o admin servir dados privados ao nível de usuário.Obrigado pelo conteúdo!
Para quem está tendo erros: Error: A partials dir must be a string or config object ou TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined. Houve uma mudança no express-handlebars o qual o nodemailer-express-handlebars faz uso. Para resolver o problema: const handlebarsOptions = { viewEngine: { extName: '.html', partialsDir: path.resolve('./src/resources/mail/'), layoutsDir: path.resolve('./src/resources/mail/'), defaultLayout: 'auth/forgot_password.html', }, viewPath: path.resolve('./src/resources/mail/'), extName: '.html', }; transport.use('compile', hbs(handlebarsOptions));
Para quem estiver fazendo essa série o Mongoose teve algumas alterações e a forma como é abordado usando o nodemailer-express-handlebars, também foi alterado, segue a alteração do arquivo *mailer.js*: github.com/yads/nodemailer-express-handlebars/issues/22 ----- const handlebarOptions = { viewEngine: { extName: '.html', partialsDir: path.resolve('./src/resources/mail/'), layoutsDir: path.resolve('./src/resources/mail/'), defaultLayout: 'email.html', }, viewPath: path.resolve('./src/resources/mail/'), extName: '.html' }; transport.use('compile', hbs(handlebarOptions)); module.exports = transport; ------ Para o arquivo authController onde ele fa o $set para fazer o reset da senha e enviar um token no e-mail com a mudança da lib o correto fica assim: ``` const now = new Date(); now.setHours(now.getHours() + 1); await User.updateOne({_id: user.id,}, { passwordResetToken: token, passwordResetExpires: now, }); ```v
@@renatosl165 possivelmente o path não está rolando corretamente ai. Tu instalou o npm i path? Se sim, dá um console.log() para ver como ele está montando o caminho dos diretórios para visualizar o arquivo em resources.
Pra quem teve esse erro: "A partials dir must be a string or config object" faz isso: const handblebarsOptions = { viewEngine: { extName: '.html', partialsDir: path.resolve('./src/resources/mail/auth/'), layoutsDir: path.resolve('./src/resources/mail/auth/'), defaultLayout: null, }, viewPath: path.resolve('./src/resources/mail/'), extName: '.html' };
Faala, André! Você conhece nossa comunidade aberta? Por lá você pode tirar essa e outras dúvidas que tiver 💜💜💜 Segue o link: www.rocketseat.com.br/comunidade
No React, eu uso o axios. Envio pelo axios as informações/dados necessarios para as rotas do express, e assim trabalho com ele no back-end. Abraço mano.
Ótima série Diego! Estou desenvolvendo uma aplicação frontend tendo como inspiração a aplicação feita na semana omnistack 10 e usando esta série pra criar o backend. É minha primeira aplicação em react e confesso estar surpreso com a facilidade de resolver os "probleminhas" que dá durante a criação. Provavelmente devido à minha falta de conhecimento ainda nessa tecnologia. Qual seria método mais seguro pra armazenar o jwt no lado do cliente? Andei lendo sobre as "fragilidades" de localStorage, sessionStorage, cookies e tals. O que vc recomendaria? Se tiver algum vídeo ou tutorial pra passar lhe agradeço. Abraço!
Estou com esse problema e n faco ideia doq pode ser... TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined at validateString (internal/validators.js:107:11) at Object.resolve (path.js:978:7)
Diego, me tire uma dúvida, por favor. Você mencionou outros serviços para usar no lugar do MailTrap, no caso como Sparkpost e Sendgrid, além desses serviços eu vou precisar contratar algo como o UolHost para ser a minha caixa me mensagens (como um Outlook, Gmail)? Não é igual ao MailTrap que além de tudo é uma caixa de mensagens?
Rodrigo, para ambiente de testes você usa o Mailtrap já que todas as mensagens (independente do destinatário) chegam em uma mesma caixa de entrada para você ter controle. Já em ambiente de produção você deve utilizar algo como Sparkpost para conseguir realmente enviar sua mensagem ao destinatário final e não a uma caixa de testes.
Muito bom o conteúdo da Rocketseat, não vi igual... tudo isso gratuito isso é muito bom! Tô precisando de uma ajuda, tô utilizando o sendgrid na minha aplicação para enviar email, vai ser feito da mesma forma que você apresentou?
Essas séries de backend da RocketSeat são muito boas, podem fazer uma série como essa de typescript fazendo uma mini loja online? Parabenizo vocês, continuem assim.
Olá, estou com o seguinte erro: Error: No recipients defined, porém esse erro é resolvido quando comento o if(err) na linha 85 do authcontroller. Após comentar o if, o programa não da erro, mas também não chega email no mailtrap. Alguem sabe onde encontro o codigo completo no github? Obrigado.
Fala brother blz! muito boa aula. seu canal é Show!.. parabéns! Mano fiquei com duvida caso eu queira trabalhar com authorização de usuarios neste sistema, como consigo fazer isso com o node? seria legal mais uma aula para serie explicando isso. vlw!
Diego, excelente aula. Queria ver como enviar um email de um token, mas, ao invés de um token em texto ou um link, um qr incorporado como imagem no email. Que poderia ser um "voucher" ou um comprovante enviado por email. Fica a dica
@@murilosaint Confere se não faltou await no seu código. Esse tipo de resposta é comum quando o Node tenta mandar uma resposta após já ter enviado, comum quando esquece o await na função assíncrona...
E como funcionaria caso você queira mandar um link para recuperação de senha ao invés do Token, e visto que a página de recuperação de senha no Front-End não tem os campos de Email e Token? Como eu passaria esses campos para o Front-End validar?
ou você utilizaria o token no link do reset_password/token e em vez de pegar do req.body pegaria pelo req.params ou no frontend você poderia setar o token nos headers e pegar ele no backend com o req.headers. Mas para mim tudo isso seria melhor feito com jwt que você passa um payload já com id do usuário no token e quando ele fizesse a requisição para resetar a senha você ja atualizava e verificava o usuário pelas informações dentro do token que você obteria depois de validar e descriptografar o token ao invés de pedir para o usuário digitar o email dele de novo.
Erro no minunto 21:00: Ao enviar uma requisição para a rota /auth/forgot_password, ocorre o seguinte erro: "A partials dir must be a string or config object". Pode me ajudar?
Fala Bruno, você pode fazer a seguinte alteração que vai dar certo: const exphbs = require('express-handlebars') const viewPath = path.resolve('./src/resources/mail/'); transport.use('compile', hbs({ viewEngine: exphbs.create({ partialsDir: path.resolve('./src/resources/mail/partials') }), viewPath, extName: '.html' }));
@@jhonatansaman8181 Fiz este procedimento e agora me retorna o seguinte erro: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined
Qual a diferença de usar o "findByIdAndUpdate" procurando o usuário pelo ID ou simplesmente dar um "user.update({...})" ? eu fiz o teste e conseguir inserir do mesmo jeito!
Pra quem estiver com problema no envio do token para o mailtrap, e com esse erro em específico: Error: A partials dir must be a string or config object , esse link pode ajudar: pt.stackoverflow.com/questions/400935/erro-nodejs-a-partials-dir-must-be-a-string-or-config-object/410499#410499
estou tendo um erro e não sei onde é que é o seguinte : [Error: ENOENT: no such file or directory, open 'C:\Users\Usuário\Desktop\Ihealth\main.handlebars'] { errno: -4058, code: 'ENOENT', syscall: 'open', path: 'C:\\Users\\Usuário\\Desktop\\Ihealth\\main.handlebars' }
Faala, dev! Você conhece nossa comunidade aberta? Por lá você pode tirar essa e outras dúvidas que tiver 💜💜 Segue o link: www.rocketseat.com.br/comunidade 🚀
Olá amigo consegui resolver este erro, indo em "src > modules > mailer.js" e editando o seguinte código: transport.use('compile', hbs({ viewEngine: { defaultLayout: undefined, partialsDir: path.resolve('./src/resources/mail/') }, viewPath: path.resolve('./src/resources/mail'), extName: '.html', })); Alterando o viewEngine, adiciona layout indefinido, e diretório padrão para os templates.
Ola, alguém pode ajudar. ? estou com o erro "Error: A partials dir must be a string or config object", já revisei várias vezes o codigo e nao acho... , isso tentando enviar o email para reset de senha.
Quando eu coloco o comando no cmd node src/index.js aparece isso ( ca7c4f6389093469fd560958299eafc5f540fdd8 2020-08-28T22:19:35.978Z ) , de mais alguém aparece isso ?
Quem não estiver conseguindo enviar o email, é pq mudou algumas configurações, se alguém estiver com problema tenho o código corrigido no meu repositório: github.com/pedrolgcs/rocketseat-courses/tree/master/TH-cam/api_node
@@PedroHenriqueTSI Oi Pedro. Vi que o seu codigo principalmente do mailer.js está bem diferente do código do Diego. Eu entro no err que está exatamente abaixo do mailer.sendMail no arquivo AuthController. Eu caio no error: 'Cannot send forgot password email' Eu coloquei um console.log antes do if e ele manda um erro que é errno: -4058, code: 'ENOENT', syscall: 'open', path: 'C:\\NODEVictorLima\\API REST-MONGO\\src\\src\ esources\\mail\\auth\\forgot_password.html' Dizendo que não nenhum arquivo ou diretório, abra e manda o endereço do html. Pensei que tivesse alguma coisa errada no html tipo tag sem fechar, mas nada. Tem ideia do que pode ser?
fui procurar na página oficial do pacote fs e encontrei que o nome foi alterado mas que ainda estava sendo usado como 'fs'. alguem sabe se já foi desocntinuado ou se tem algum problema utilizar ele dessa forma? (yarn add fs)? fonte: www.npmjs.com/package/fs
Depois da utilização do Token, por questões de segurança creio ser importante invalidar o Reset Token, obrigado o usuário a gerar novamente caso queira realizar um novo reset de password. em AuthController.js, depois de verificar se o token é válido: user.password = password; user.passwordResetToken = undefined; await user.save(); res.send();
Estou tendo um erro diferente, quando faço a requisição ele me retorna isso, segue abaixo o código do meu arquivo err TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined const path = require('path'); const nodemailer = require('nodemailer'); const hbs = require('nodemailer-express-handlebars'); const exphbs = require('express-handlebars') const { host, port, user, pass} = require('../config/mail.json'); var transport = nodemailer.createTransport({ host, port, auth: { user, pass } }); const viewPath = path.resolve('./src/resources/mail/');
O meu ocorre o seguinte erro { [Error: ENOENT: no such file or directory, open 'D:\Projetos\E-MODA\emoda-api\server\mail\esqueceu_senha.html.html'] errno: -4058, code: 'ENOENT', syscall: 'open', path: 'D:\\Projetos\\E-MODA\\emoda-api\\server\\mail\\esqueceu_senha.html.html' }
Boa tarde amigo, provavelmente voce ja tenha conseguido arrumar, mas é só um erro de caminho até a pasta do html ou é apenas colocar o nome do arquivo sem extensão. const handlebarOptions = { viewEngine: { extName: '.html', partialsDir: './src/resources/mail/', layoutsDir: path.resolve('./src/resources/mail/'), defaultLayout: 'forgot_password', }, viewPath: path.resolve('./src/resources/mail/'), extName: '.html', }; transport.use('compile', hbs(handlebarOptions));
Cara eu estou adorando seus videos, mas encontrei um problema e não consigo resolver SyntaxError: Unexpected token } in JSON at position 31 at JSON.parse () at parse (C:\ApiNode ode_modules\body-parser\lib\types\json.js:89:19) at C:\ApiNode ode_modules\body-parser\lib ead.js:121:18 at invokeCallback (C:\ApiNode ode_modules aw-body\index.js:224:16) at done (C:\ApiNode ode_modules aw-body\index.js:213:7) at IncomingMessage.onEnd (C:\ApiNode ode_modules aw-body\index.js:273:7) at IncomingMessage.emit (events.js:127:13) at endReadableNT (_stream_readable.js:1101:12) at process._tickCallback (internal/process/next_tick.js:114:19) o que pode ser? não consigo encontrar o problema...vlw
A cada vez que o usuário é salvo, a senha é criptografada, então, se eu editar qualquer coisa e salvar, a senha vai ser meio que perdida, porque vai ser criptografada novamente, não?
Alguem consegue me ajudar ? na parte de enviar o e-mail nao consigo usar um template, quando o caminho apontado esta correto ele gera o seguinte erro: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined quando o arquivo html nao é encontrado ele gera o erro: { [Error: ENOENT: no such file or directory, open 'D:\mail\auth c.html'] errno: -4058, code: 'ENOENT', syscall: 'open', path: 'D:\\mail\\auth\ c.html' }
é normal o insommia funciona e continua carregando sem parar? ja aconteceu de cria o registro e continua carregando ou pega a requisição e não parar, tenho que cancelar pra parar
@@silaspaes7773 consegue nada, como meu projeto é grande e eu preciso entregar no final do semestre eu deixei de lado por enquanto a recuperação de senha
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received an instance of MailMessage Estou passando por esse error alguém sabe onde é o empecilho, por favor
Diego, tenho me deparado com este erro, intermitente: o POST é enviado vazio pelo Insomnia ou recebido vazio pela API. Colocando console.log(req.body) bem no início do código, retorna { }.
Diego, está retornando o erro "A partials dir must be a string or config object" com o envio de e-mail, pesquisei e vi que houveram atualizações, mas não consigo implementar, algo relacionado a adicionar viewPath e extName, alguém sabe a solução mais adequada?
Voce precisa criar um objeto de opcoes para o compile no mailer.js: const handlebarOptions = { viewEngine: { extName: '.html', defaultLayout: null, partialsDir: path.join('./src/resources/mail'), layoutsDir: path.join('./src/resources/mail'), }, viewPath: path.join('./src/resources/mail'), extName: '.html', } transport.use('compile', hbs(handlebarOptions)); e no controller voce invoca a operacao passando somente o template: mailer.sendMail({ to: email, from: 'send@email.com', template: '/auth/forgot_password', context: { token, name }, }
Serie sensacional! Meus parabéns.. Estou com um probleminha, ao executar a url forgot_password pela Insomnia retornou o seguinte erro: Error: A partials dir must be a string or config object. Alguém passou por esse problema ?
Fala Gleydisson, a API do Nodemailer mudou um pouquinho e na config agora você precisa passar um caminho onde guarda templates parciais. É só passar uma pasta partials qualquer: const viewPath = path.resolve(__dirname, "..", "views", "emails"); transport.use( "compile", hbs({ viewEngine: exphbs.create({ partialsDir: path.resolve(viewPath, "partials") }), viewPath, extName: ".hbs" }) );
@@rocketseat Fiz como falou e resolveu imediatamente o problema. Já sou fã do trabalho de vcs. Moro em toronto canadá e divulguei seu canal para alguns colegas. Obrigado!
Também estou travado com o mesmo problema, ele até gera o token no banco de dados, porém não envia por e-mail. está dando a mensagem abaixo no log: Error: A partials dir must be a string or config object at ExpressHandlebars. (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/express-handlebars/3.1.0/node_modules/express-handlebars/lib/express-handlebars.js:71:19) at Array.map () at ExpressHandlebars.getPartials (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/express-handlebars/3.1.0/node_modules/express-handlebars/lib/express-handlebars.js:54:33) at ExpressHandlebars.renderView (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/express-handlebars/3.1.0/node_modules/express-handlebars/lib/express-handlebars.js:203:14) at TemplateGenerator.render (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer-express-handlebars/3.1.0/node_modules/nodemailer-express-handlebars/lib/generator.js:21:21) at /rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer-express-handlebars/3.1.0/node_modules/nodemailer-express-handlebars/lib/index.js:9:19 at processPlugins (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer/6.4.2/node_modules/nodemailer/lib/mailer/index.js:279:13) at err (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer/6.4.2/node_modules/nodemailer/lib/mailer/index.js:283:17) at Mail._convertDataImages (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer/6.4.2/node_modules/nodemailer/lib/mailer/index.js:387:20) at Mail._defaultPlugins.compile.args (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer/6.4.2/node_modules/nodemailer/lib/mailer/index.js:31:41) at processPlugins (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer/6.4.2/node_modules/nodemailer/lib/mailer/index.js:279:13) at Mail._processPlugins (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer/6.4.2/node_modules/nodemailer/lib/mailer/index.js:287:9) at Mail.sendMail (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer/6.4.2/node_modules/nodemailer/lib/mailer/index.js:164:14) at router.post (/app/src/app/controllers/authController.js:81:10) at process._tickCallback (internal/process/next_tick.js:68:7)
Quem tiver problema no teste aos 21:00. colocar esse código aqui no arquivo mailer.js
transport.use('compile', hbs({
viewEngine: {
defaultLayout: undefined,
partialsDir: path.resolve('./src/resources/mail/')
},
viewPath: path.resolve('./src/resources/mail/'),
extName: '.html',
}));
Abraço!
Valeeu pela dica! 💜
Show colega...digitei o código no arquivo mailer.js conforme sua dica e funcionou na hora...parabéns...obrigado
@@paulomorenodev nada cara! A gente tem é que se ajudar!
muito obrigado!!!!
Valeu! Tava quebrando a cabeça aqui.
Para quem estiver com problema no sendMail
PARA O MODULE
const path = require('path')
const nodemailer = require('nodemailer')
const smtpTransport = require('nodemailer-smtp-transport')
const hbs = require('nodemailer-express-handlebars')
const { host, port, user, pass } = require('../config/mail.json')
const transport = nodemailer.createTransport(smtpTransport({
host,
port,
auth: { user, pass }
}));
const handlebarOptions = {
viewEngine: {
extName: '.html',
partialsDir: path.resolve('./src/resources/mail/auth/'),
layoutsDir: path.resolve('./src/resources/mail/auth/'),
defaultLayout: 'forgot_password.html',
},
viewPath: path.resolve('./src/resources/mail/auth/'),
extName: '.html',
};
transport.use('compile', hbs(handlebarOptions));
module.exports = transport
PARA O CONTROLLER
await mailer.sendMail({
to: email,
from: 'diego3g@rocketset.com.br',
subject: 'Test',
template: 'forgot_password',
context: { token }
})
Na realidade, no 'const handlebarOptions, é só deixar o defaultLayout em defaultLayout: null;
Aí caso você queira usar outros layouts, não vai setar sempre no de forgot_password.
segui a sugestao mas ainda tenho o msm erro
@@rhiancastro1263 Na verdade ele só pega o defaultLayout se na controller você não especifica o template
Pra quem teve problema em 15:04 com deprecated
await User.findByIdAndUpdate(user.id, {
'$set': {
{ passwordResetToken: token, passwordResetExpires: now }
}
});
A solução que eu achei
await User.updateOne(
{ _id: user.id },
{ passwordResetToken: token, passwordResetExpires: now },
);
Tbm tive problema no Mailer por que ele pedi um caminho para importar um template(Eu li mais sobre isso. Porém não tenho certeza se o que eu fiz é a melhor solução). Então eu coloquei os parametros para caso queira colocar o template mas o desativei so para testar a aplicação sem precisar de um.
transport.use(
'compile',
hbs({
viewEngine: {
extName: '.hbs',
partialsDir: path.resolve('resources', 'templates'),
defaultLayout: false,
},
viewPath: path.resolve('resources', 'mail'),
extName: '.html',
}),
);
O resultado é o mesmo.
Espero ter ajudado
Muito obg, me ajudou muito essa solução a outra não estava dando certo
É só comigo que dá uma sensação de estranheza ver a lógica de negócio dentro das rotas? Fora isso, o conteúdo é muito bom. Vlw Diego por disponibilizar estes conteúdos, está sendo muito bom para os meus estudos com NodeJS.
api geralmente é nesse estilo
Eu separei as rotas, fica mais limpo.
é so didatico ,geralmente os devs separam
@@matheusmgp1 mais didático que deixar organizado as rotas e levar as regras pro controller?
Acho que não tô bem então, porque pensa num ser que ficou confuso pra caralho, principalmente vindo do Laravel: eu.
Como ficaria dividido a estrutura?
Aula sensacional!!
para quem está com o erro "A partials dir must be a string or config object."
mudei uma parte do "modules/mailer.js" para:
transport.use('compile', hbs({
viewEngine: {
layoutsDir: path.resolve('./src/resources/mail/'),
partialsDir: path.resolve('./src/resources/mail/'),
},
viewPath: path.resolve('./src/resources/mail/'),
extName: '.html',
}));
e criei o arquivo "main.handlebars" no caminho "resources/mail", com o seguinte código:
My Awesome App
{{{body}}}
Quando enviar o email, ele vai substituir o "{{{body}}}" pelo conteúdo do arquivo "forgot_password.html" ;)
Obrigado @Muriel, resolveu meu problema.
Muito massa esses conteúdos gratuitos que a Rocket nos proporciona. Salva a vida de muita gente kkk
Cara, esses vídeos estão me ajudando muito, e a galera comentando e ajudando também. Obrigado a todos
Fala Marcelo! Valeeu pelo feedback! 💜
UHUUU!! Muito bom o conteúdo, existem algumas diferenças com relação ao nodemailer-express-handlebars, na última versão para configuração do viewEngine, ou pelo menos eu configurei de forma diferente para conseguir funcionar.
Coloquei assim:
transport.use('compile', hbs({
viewEngine: {
extname: '.html',
layoutsDir: 'src/resources/mail/',
defaultLayout: 'forgot_password',
partialsDir: 'src/resources/mail/',
},
viewPath: 'src/resources/mail/',
extName: '.html'
}));
O que eu fiz foi para o desafio NLW 2.0, ainda caminhando!! Usando o typescript, apesar que o handlebars não tem @types
Mermão, esse maluco é uma máquina de produzir código.
Mais uma vez, tenho que parabenizar pelo trabalho, muito bem feito.
Fazem toda a diferença para quem está iniciando, incentivando cada vez mais novos desenvolvedores a seguirem no caminho, e empreendendo cada vez mais.
Sensacional! Você é fera demais Diego. Está me ajudando muito!
Mano faz uma aula sobre Autorização.. vc explica muito bem parabens!
Show de bola, Diego. Teus vídeos estão ajudando muito no meu projeto de criar um portal de recepção de arquivos para a gráfica onde trabalho.
Tooooop meu velho! Uma das melhores series que eu já vi aqui no youtube, parabéns mesmo cara! Vou acompanhar até o final da serie e logo depois vou começar a de react
Shooooooow!!! Liberamos inscrições pro nosso treinamento de NodeJS hoje se tiver interessado: rocketseat.com.br/gonode
Top, eu tenho muita dificuldade em organizar meu projeto, a forma apresentada é sensacional
Show demais, conteúdo muito prático e sem enrolação
para quem estiver tendo problemas com o envio de email aos 21:00:
const transport = nodemailer.createTransport({
host,
port,
auth: {
user,
pass: password
//alterar o nome da chave para ''pass'', passando o valor de password
}
})
Cara!!!!!! Sensacional! Muito didático, dinámico!
Parabéns cara, seus vídeos são bem esclarecedores e com uma ótima didática.
Pra quem tiver tendo esse problema de diretorio =>
[Error: ENOENT: no such file or directory, open 'D:\projetos
ode\server_rocket\src\src
esources\mail\auth\forgot_password.html'] {
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'D:\\projetos\
ode\\server_rocket\\src\\src\
esources\\mail\\auth\\forgot_password.html'
}
Eu consegui resolver assim, e agora está sendo enviado com sucesso o email com token.
transport.use(
"compile",
hbs({
viewEngine: {
defaultLayout: undefined,
partialsDir: path.resolve("../src/resources/mail/"),
},
viewPath: path.resolve("../src/resources/mail/"),
extName: ".html",
})
);
Muito bom mesmo!!!! Parabéns ao Diego Fernandes e a todos da Rocketseat
Muito bom mano, você possui uma ótima didática, parabéns
Seu conteúdo é muito bom! Com certeza está ajudando muito a comunidade!
Uma pergunta: Por que no node você usa require e não import?
Obrigado.
Parabéns amigo, excelente treinamento. Demorei mas achei um de qualidade!!!
Mto bom mesmo! poderia fazer um video com a parte do front em react :)
Cara, que aula massa ! Parabéns Diego.
Parabéns, muito boa explicação!
Você poderia incluir na sua série, autenticação com diferentes papéis (roles) de usuários
Sim, isso mesmo tenho muita dificuldade nisso em trazer a informação correspondente de cada usuários, onde cada um possui um nível permissão, podendo acessar somente algumas páginas ou executar determinadas funções. Espero que tenha isso no curso para ser 1000. Mas já está de parabéns pelas aulas disponibilizadas.
Kr, excelente seu método de ensino! Muito bom mesmo, obrigado!
Para, muito bom mesmo! Só gratidão!
Que conteúdo INSANO!
Fala Diego, to gostando demais dessa série. Apesar de ja trabalhar com isso, algumas coisas que voce esta ensinando resolvem alguns problemas que por vezes surgiram comigo. Mas eu gostaria de ver como ficaria melhor essa organização de controllers e rotas, uma forma de modularizar mais, separando-os e talz. Fica como sugestão. E parabéns pelo conteúdo man!
Em breve melhorarei ainda mais essa estrutura, estamos indo a cada aula entendendo o que está se tornando repetitivo e verboso para resolver cada item no seu tempo. A separação de rotas é muito legal e provavelmente teremos nos próximos vídeos. Valeu Italo.
Aula boa demais como sempre, obrigado!
ótimo conteúdo, tu explica muito bem ...
Muito bom mano! Obrigado pelas aulas!
Ótima série, valeu demais Diego :-)
Vaaleu, André! 💜💜 Diego arrasa né?
Ajudando demais!
Muito top ! Conteúdo excelente !
Valeeeu demais, Lucas! 💜 🚀
Eu gostaria de ver série sobre ACL,NOSQL com mongo, onde o admin possa ver menus que o usuário comum não pode,o admin pode controlar regras que o o user normal não pode.Admin controla o que os níveis de users podem ou não ver e fazer.
Usando apis públicas e privadas de terceiros, para servir dados para o usuário e para o admin.Criar uma regra de negócio para o admin servir dados privados ao nível de usuário.Obrigado pelo conteúdo!
Para quem está tendo erros: Error: A partials dir must be a string or config object ou TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined.
Houve uma mudança no express-handlebars o qual o nodemailer-express-handlebars faz uso. Para resolver o problema:
const handlebarsOptions = {
viewEngine: {
extName: '.html',
partialsDir: path.resolve('./src/resources/mail/'),
layoutsDir: path.resolve('./src/resources/mail/'),
defaultLayout: 'auth/forgot_password.html',
},
viewPath: path.resolve('./src/resources/mail/'),
extName: '.html',
};
transport.use('compile', hbs(handlebarsOptions));
Para quem estiver fazendo essa série o Mongoose teve algumas alterações e a forma como é abordado usando o nodemailer-express-handlebars, também foi alterado, segue a alteração do arquivo *mailer.js*:
github.com/yads/nodemailer-express-handlebars/issues/22
-----
const handlebarOptions = {
viewEngine: {
extName: '.html',
partialsDir: path.resolve('./src/resources/mail/'),
layoutsDir: path.resolve('./src/resources/mail/'),
defaultLayout: 'email.html',
},
viewPath: path.resolve('./src/resources/mail/'),
extName: '.html'
};
transport.use('compile', hbs(handlebarOptions));
module.exports = transport;
------
Para o arquivo authController onde ele fa o $set para fazer o reset da senha e enviar um token no e-mail com a mudança da lib o correto fica assim:
```
const now = new Date();
now.setHours(now.getHours() + 1);
await User.updateOne({_id: user.id,},
{
passwordResetToken: token,
passwordResetExpires: now,
});
```v
[Error: ENOENT: no such file or directory, open 'C:\Users
enat\Desktop\turistando-api\src
esources\mail\email.html']
cara rolou isso cmg :(
@@renatosl165 possivelmente o path não está rolando corretamente ai. Tu instalou o npm i path?
Se sim, dá um console.log() para ver como ele está montando o caminho dos diretórios para visualizar o arquivo em resources.
Teu mailer pode ficar assim:
gist.github.com/cristofersousa/f24eca1a6a537b997317fb4568b96b97
@@CristoferSousa cara eu achei a resposta um dos comentários aqui no vídeo, mas n sei explicar exatamente o que eu fiz
Pra quem teve esse erro: "A partials dir must be a string or config object"
faz isso:
const handblebarsOptions = {
viewEngine: {
extName: '.html',
partialsDir: path.resolve('./src/resources/mail/auth/'),
layoutsDir: path.resolve('./src/resources/mail/auth/'),
defaultLayout: null,
},
viewPath: path.resolve('./src/resources/mail/'),
extName: '.html'
};
Faala, André! Você conhece nossa comunidade aberta? Por lá você pode tirar essa e outras dúvidas que tiver 💜💜💜 Segue o link: www.rocketseat.com.br/comunidade
@@rocketseat blz, vou entrar lá 👍
muito bom me ajudou bastante
Parabéns cara está excelente!!!
Gostaria de saber como eu consumo a API em um front-and usando React?
Gostaria de ver.
No React, eu uso o axios. Envio pelo axios as informações/dados necessarios para as rotas do express, e assim trabalho com ele no back-end. Abraço mano.
Valeu ai Diego...
A parte de criptografar o token de redefiniçãao, não poderia ser usado com o proprio Bcrypt ?
Ótima série Diego! Estou desenvolvendo uma aplicação frontend tendo como inspiração a aplicação feita na semana omnistack 10 e usando esta série pra criar o backend.
É minha primeira aplicação em react e confesso estar surpreso com a facilidade de resolver os "probleminhas" que dá durante a criação. Provavelmente devido à minha falta de conhecimento ainda nessa tecnologia.
Qual seria método mais seguro pra armazenar o jwt no lado do cliente? Andei lendo sobre as "fragilidades" de localStorage, sessionStorage, cookies e tals. O que vc recomendaria? Se tiver algum vídeo ou tutorial pra passar lhe agradeço. Abraço!
Estou com esse problema e n faco ideia doq pode ser...
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined
at validateString (internal/validators.js:107:11)
at Object.resolve (path.js:978:7)
Tenta assim:
const handlebarOptions = {
viewEngine: {
extName: '.html',
partialsDir: path.resolve('./src/resources/mail/'),
layoutsDir: path.resolve('./src/resources/mail/'),
defaultLayout: '',
},
viewPath: path.resolve('./src/resources/mail/'),
extName: '.html',
}
transport.use('compile', hbs(handlebarOptions))
@@rafaelnilton1 esse diretório mail ficaria vazio msm ?
@@rafaelnilton1 multissimo obrigado cara o seu comentario me ajudo, mas tive que tira o src pra funciona como o amigo de cima alerto
@@iagorochaporto3042 sim
@@cedrio1027 como assim cara? nao entendi... pode mandar o block de código para eu conseguir entender por favor estou com esse problema
Muito bom Diego! Parabéns a você e a RocketSeat!
Uma dúvida: não seria interessante atribuir nulo no passwordResetToken e passwordResetExpires ?
Sim Julian, acabei esquecendo no fim da aula hehe! Abraço e obrigado pelo feedback!
Opa, eu fiz isso em kk. Mas não setei como nulo, setei como undefined
Vlw cara, vc ganhou +1 seguidor ahaha
it's done
obrigado rocket.!
Show!! Muito bom!!!
Poderia conectar essa api no react js
Minha dúvida é, se é melhor usar o jwt do que criar e guardar em novos campos na db
Diego, me tire uma dúvida, por favor. Você mencionou outros serviços para usar no lugar do MailTrap, no caso como Sparkpost e Sendgrid, além desses serviços eu vou precisar contratar algo como o UolHost para ser a minha caixa me mensagens (como um Outlook, Gmail)? Não é igual ao MailTrap que além de tudo é uma caixa de mensagens?
Rodrigo, para ambiente de testes você usa o Mailtrap já que todas as mensagens (independente do destinatário) chegam em uma mesma caixa de entrada para você ter controle. Já em ambiente de produção você deve utilizar algo como Sparkpost para conseguir realmente enviar sua mensagem ao destinatário final e não a uma caixa de testes.
Muito bom o conteúdo da Rocketseat, não vi igual... tudo isso gratuito isso é muito bom! Tô precisando de uma ajuda, tô utilizando o sendgrid na minha aplicação para enviar email, vai ser feito da mesma forma que você apresentou?
eu estou com um problema aqui, no teste aos 16:50, fica aparecendo error on forgot password, try again.
Essas séries de backend da RocketSeat são muito boas, podem fazer uma série como essa de typescript fazendo uma mini loja online? Parabenizo vocês, continuem assim.
Muito bom mesmo!!!
Observação: NÃO É NECESSÁRIO INSTALAR O FS E O PATH MAIS, apenas importe do node
Olá, estou com o seguinte erro: Error: No recipients defined, porém esse erro é resolvido quando comento o if(err) na linha 85 do authcontroller. Após comentar o if, o programa não da erro, mas também não chega email no mailtrap. Alguem sabe onde encontro o codigo completo no github? Obrigado.
Fala brother blz! muito boa aula. seu canal é Show!.. parabéns!
Mano fiquei com duvida caso eu queira trabalhar com authorização de usuarios neste sistema, como consigo fazer isso com o node? seria legal mais uma aula para serie explicando isso.
vlw!
Consegue sim, procure por Node ACL que deve achar alguns pacotes com essa funcionalidade. Abração!
Boa vou pesquisar aqui!.. existe a possibilidade de adicionar mais uma aula a está serie.. abordando esse assunto? seria Massa! vlw mano Obriado!
Manda mais uma aula ae com ACL Brother! valeu!
Diego, excelente aula. Queria ver como enviar um email de um token, mas, ao invés de um token em texto ou um link, um qr incorporado como imagem no email. Que poderia ser um "voucher" ou um comprovante enviado por email. Fica a dica
Obrigado. Muito bom
Vaaaleu, Ricardo! 💜
Estou tento um erro:
Error: A partials dir must be a string or config object.
Vem direto do handle-bars. :(
Resolvi esse erro nesse seguindo as informações desse link: pt.stackoverflow.com/questions/400935/erro-nodejs-a-partials-dir-must-be-a-string-or-config-object
Meu código ficou assim:
function ExpressHandlebars(config) {
// Config properties with defaults.
utils.assign(this, {
handlebars : Handlebars,
extname : '.handlebars',
layoutsDir : './src/app/resources/mail/auth/', // Default layouts directory is relative to `express settings.view` + `layouts/`
partialsDir : './src/app/resources/mail/auth/', // Default partials directory is relative to `express settings.view` + `partials/`
defaultLayout : 'forgot_password.html',
helpers : undefined,
compilerOptions: undefined,
}, config);
Espero ter ajudado, até...
consegui resolver este erro. Mas agora dá outro erro: Can't set headers after they are sent
@@murilosaint Confere se não faltou await no seu código. Esse tipo de resposta é comum quando o Node tenta mandar uma resposta após já ter enviado, comum quando esquece o await na função assíncrona...
@@kverakroove show! Esse video é de 2017, o plugin sofreu atualizações e essa configuração é obrigatória. Muito obrigado! Abçs
@@kverakroove Vallleuuuuussssss!!!! Deu bom aqui....
E como funcionaria caso você queira mandar um link para recuperação de senha ao invés do Token, e visto que a página de recuperação de senha no Front-End não tem os campos de Email e Token? Como eu passaria esses campos para o Front-End validar?
ou você utilizaria o token no link do reset_password/token e em vez de pegar do req.body pegaria pelo req.params ou no frontend você poderia setar o token nos headers e pegar ele no backend com o req.headers. Mas para mim tudo isso seria melhor feito com jwt que você passa um payload já com id do usuário no token e quando ele fizesse a requisição para resetar a senha você ja atualizava e verificava o usuário pelas informações dentro do token que você obteria depois de validar e descriptografar o token ao invés de pedir para o usuário digitar o email dele de novo.
E obrigatorio a passagem do APP para cada uma das rotas ? Se nao passar oque impacta ?
Erro no minunto 21:00: Ao enviar uma requisição para a rota /auth/forgot_password, ocorre o seguinte erro: "A partials dir must be a string or config object". Pode me ajudar?
Fala Bruno, você pode fazer a seguinte alteração que vai dar certo:
const exphbs = require('express-handlebars')
const viewPath = path.resolve('./src/resources/mail/');
transport.use('compile', hbs({
viewEngine: exphbs.create({ partialsDir: path.resolve('./src/resources/mail/partials') }),
viewPath,
extName: '.html'
}));
@@jhonatansaman8181 Mas vou colocar esse código onde?
@@BrunoCosta_88 mailer.js dentro de modules
@@jhonatansaman8181 Fiz este procedimento e agora me retorna o seguinte erro: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined
@@DiegoTesch Resolveu o problema ? estou com o mesmo aqui.
Qual a diferença de usar o "findByIdAndUpdate" procurando o usuário pelo ID ou simplesmente dar um "user.update({...})" ? eu fiz o teste e conseguir inserir do mesmo jeito!
Pra quem estiver com problema no envio do token para o mailtrap, e com esse erro em específico:
Error: A partials dir must be a string or config object ,
esse link pode ajudar:
pt.stackoverflow.com/questions/400935/erro-nodejs-a-partials-dir-must-be-a-string-or-config-object/410499#410499
Estou com erro "internal/modules/cjs/loader.js 883 throw err; " aparece aqui na parte do tutorial 15:50. Se alguém puder me dá uma luz ficarei grato.
o JSON Web Token (JWT), substitui o OAuth2 e o OpenID Connect?
Poderia acrescentar a parte de autenticação com os dados do Facebook e Google?
Ficarei bastante feliz.
estou tendo um erro e não sei onde é que é o seguinte :
[Error: ENOENT: no such file or directory, open 'C:\Users\Usuário\Desktop\Ihealth\main.handlebars'] {
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'C:\\Users\\Usuário\\Desktop\\Ihealth\\main.handlebars'
}
Faala, dev! Você conhece nossa comunidade aberta? Por lá você pode tirar essa e outras dúvidas que tiver 💜💜 Segue o link: www.rocketseat.com.br/comunidade 🚀
Olá amigo consegui resolver este erro, indo em "src > modules > mailer.js" e editando o seguinte código:
transport.use('compile', hbs({
viewEngine: {
defaultLayout: undefined,
partialsDir: path.resolve('./src/resources/mail/')
},
viewPath: path.resolve('./src/resources/mail'),
extName: '.html',
}));
Alterando o viewEngine, adiciona layout indefinido, e diretório padrão para os templates.
@@TheMatheusProduction Obrigado amigo!
@@TheMatheusProduction Ajudou demais cara, mt obrigada!
@@rafaelmoraes1288 opa de nada mano!
Qual razão não usar o consign inves de fazer esse uso do path e do fs?
Ola, alguém pode ajudar. ? estou com o erro "Error: A partials dir must be a string or config object", já revisei várias vezes o codigo e nao acho...
, isso tentando enviar o email para reset de senha.
Estava com esse problema, resolve assim:
No arquivo mailer.js da pasta modules. Substitua:
transport.use('compile', hbs({
viewEngine: 'handlebars',
viewPath: path.resolve('./resources/mail/'),
extName: '.html'
}))
Por:
const handlebarOptions = {
viewEngine: {
extName: '.html',
partialsDir: path.resolve('./src/resources/mail/'),
layoutsDir: path.resolve('./src/resources/mail/'),
defaultLayout: '',
},
viewPath: path.resolve('./src/resources/mail/'),
extName: '.html',
}
transport.use('compile', hbs(handlebarOptions))
@@adrianoasg10 Valeeeeeeeeeeu!
@@adrianoasg10 Man, thanks for your help, i was suffering here with this error
@@adrianoasg10 eu te amo
@@adrianoasg10 Porra man, salvou minha vida!! Abraço
Quando eu coloco o comando no cmd node src/index.js aparece isso ( ca7c4f6389093469fd560958299eafc5f540fdd8 2020-08-28T22:19:35.978Z ) ,
de mais alguém aparece isso ?
Olá, isso é pq pra tratar um erro que aconteceu o Diego colocou console.log(token, now). Só por isso ta aparecendo no teu terminal.
Que caracter é aquele em 3:37 depois do !== 0 ? é um & com fonte diferente ?
Isso, são apenas dois && :)
Fala Diego, tudo bem? ainda vai sair mais aulas?
Quem não estiver conseguindo enviar o email, é pq mudou algumas configurações, se alguém estiver com problema tenho o código corrigido no meu repositório: github.com/pedrolgcs/rocketseat-courses/tree/master/TH-cam/api_node
Vlw! Muito obrigado.
Este repositório não existe mais =/
@@g-laveli aqui amigo: github.com/pedrolgcs/express-auth-crud-mongoDB é pq refatorei algumas coisas, qualquer dúvida pode mandar
@@PedroHenriqueTSI Oi Pedro. Vi que o seu codigo principalmente do mailer.js está bem diferente do código do Diego.
Eu entro no err que está exatamente abaixo do mailer.sendMail no arquivo AuthController. Eu caio no error: 'Cannot send forgot password email'
Eu coloquei um console.log antes do if e ele manda um erro que é
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'C:\\NODEVictorLima\\API REST-MONGO\\src\\src\
esources\\mail\\auth\\forgot_password.html'
Dizendo que não nenhum arquivo ou diretório, abra e manda o endereço do html. Pensei que tivesse alguma coisa errada no html tipo tag sem fechar, mas nada.
Tem ideia do que pode ser?
fui procurar na página oficial do pacote fs e encontrei que o nome foi alterado mas que ainda estava sendo usado como 'fs'. alguem sabe se já foi desocntinuado ou se tem algum problema utilizar ele dessa forma? (yarn add fs)?
fonte: www.npmjs.com/package/fs
muito bom
Depois da utilização do Token, por questões de segurança creio ser importante invalidar o Reset Token, obrigado o usuário a gerar novamente caso queira realizar um novo reset de password.
em AuthController.js, depois de verificar se o token é válido:
user.password = password;
user.passwordResetToken = undefined;
await user.save();
res.send();
Estou tendo um erro diferente, quando faço a requisição ele me retorna isso, segue abaixo o código do meu arquivo
err TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined
const path = require('path');
const nodemailer = require('nodemailer');
const hbs = require('nodemailer-express-handlebars');
const exphbs = require('express-handlebars')
const { host, port, user, pass} = require('../config/mail.json');
var transport = nodemailer.createTransport({
host,
port,
auth: { user, pass }
});
const viewPath = path.resolve('./src/resources/mail/');
transport.use('compile', hbs({
viewEngine: exphbs.create({ partialsDir: path.resolve('./src/resources/mail/partials') }),
viewPath,
extName: '.html'
}));
module.exports = transport;
O meu ocorre o seguinte erro
{ [Error: ENOENT: no such file or directory, open 'D:\Projetos\E-MODA\emoda-api\server\mail\esqueceu_senha.html.html']
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path:
'D:\\Projetos\\E-MODA\\emoda-api\\server\\mail\\esqueceu_senha.html.html' }
Boa tarde amigo, provavelmente voce ja tenha conseguido arrumar, mas é só um erro de caminho até a pasta do html ou é apenas colocar o nome do arquivo sem extensão.
const handlebarOptions = {
viewEngine: {
extName: '.html',
partialsDir: './src/resources/mail/',
layoutsDir: path.resolve('./src/resources/mail/'),
defaultLayout: 'forgot_password',
},
viewPath: path.resolve('./src/resources/mail/'),
extName: '.html',
};
transport.use('compile', hbs(handlebarOptions));
Muito top
Cara eu estou adorando seus videos, mas encontrei um problema e não consigo resolver
SyntaxError: Unexpected token } in JSON at position 31
at JSON.parse ()
at parse (C:\ApiNode
ode_modules\body-parser\lib\types\json.js:89:19)
at C:\ApiNode
ode_modules\body-parser\lib
ead.js:121:18
at invokeCallback (C:\ApiNode
ode_modules
aw-body\index.js:224:16)
at done (C:\ApiNode
ode_modules
aw-body\index.js:213:7)
at IncomingMessage.onEnd (C:\ApiNode
ode_modules
aw-body\index.js:273:7)
at IncomingMessage.emit (events.js:127:13)
at endReadableNT (_stream_readable.js:1101:12)
at process._tickCallback (internal/process/next_tick.js:114:19)
o que pode ser? não consigo encontrar o problema...vlw
era uma virgula perdida..
@@carlosguedesjr ja fiquei uma tarde preso por conta de uma virgula perdida na ferramenta de testes de API kkkkk
Didática é muito boa, mas muito rápido tenta ser um pouquinho mais devagar, de resto 100%
A cada vez que o usuário é salvo, a senha é criptografada, então, se eu editar qualquer coisa e salvar, a senha vai ser meio que perdida, porque vai ser criptografada novamente, não?
Alguem consegue me ajudar ? na parte de enviar o e-mail nao consigo usar um template, quando o caminho apontado esta correto ele gera o seguinte erro:
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined
quando o arquivo html nao é encontrado ele gera o erro:
{ [Error: ENOENT: no such file or directory, open 'D:\mail\auth
c.html']
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'D:\\mail\\auth\
c.html' }
Blza? Vc consegui resolver? Estou com um erro bem parecido
é normal o insommia funciona e continua carregando sem parar? ja aconteceu de cria o registro e continua carregando ou pega a requisição e não parar, tenho que cancelar pra parar
Se não tiver nem uma forma de retorno ele nao para nunca. para ele parar de carregar você pode fazer um retorno vazio return res.send();
LIKEEE!
Eu tentei usar o comando mongod, mas diz que não é reconhecido. O q eu deveria fazer?
Alguém pode me ajudar? esta parando no mailer.sendMail e não da erro algum eu já vi e revi o video 10 vezes mais não consigo solucionar o problema
conseguiu resolver? o meu ta dando Error: Cannot find module '../app/modules/mailer'
@@silaspaes7773 consegue nada, como meu projeto é grande e eu preciso entregar no final do semestre eu deixei de lado por enquanto a recuperação de senha
Coloca os nomes dessas músicas que toca no final ai! são muito boas tb!
Esse é Best of You do Foo Fighters :D
Essa ai era a única boa que eu conhecia kkkkkk
INTRO: Queens Of The Stone Age - 3's & 7's --- LINK: th-cam.com/video/BgVfjXA_QY0/w-d-xo.html
Assistindo em 2021
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received an instance of MailMessage
Estou passando por esse error alguém sabe onde é o empecilho, por favor
se tivesse o front como iria fazer?
Diego, tenho me deparado com este erro, intermitente: o POST é enviado vazio pelo Insomnia ou recebido vazio pela API. Colocando console.log(req.body) bem no início do código, retorna { }.
Nem perca tempo respondendo, foi um erro besta que cometi. Colocando no Header: Content-Type: application/json, tudo se resolveu.
Diego, está retornando o erro "A partials dir must be a string or config object" com o envio de e-mail, pesquisei e vi que houveram atualizações, mas não consigo implementar, algo relacionado a adicionar viewPath e extName, alguém sabe a solução mais adequada?
Voce precisa criar um objeto de opcoes para o compile no mailer.js:
const handlebarOptions = {
viewEngine: {
extName: '.html',
defaultLayout: null,
partialsDir: path.join('./src/resources/mail'),
layoutsDir: path.join('./src/resources/mail'),
},
viewPath: path.join('./src/resources/mail'),
extName: '.html',
}
transport.use('compile', hbs(handlebarOptions));
e no controller voce invoca a operacao passando somente o template:
mailer.sendMail({
to: email,
from: 'send@email.com',
template: '/auth/forgot_password',
context: { token, name },
}
Serie sensacional! Meus parabéns.. Estou com um probleminha, ao executar a url forgot_password pela Insomnia retornou o seguinte erro: Error: A partials dir must be a string or config object. Alguém passou por esse problema ?
Fala Gleydisson, a API do Nodemailer mudou um pouquinho e na config agora você precisa passar um caminho onde guarda templates parciais. É só passar uma pasta partials qualquer:
const viewPath = path.resolve(__dirname, "..", "views", "emails");
transport.use(
"compile",
hbs({
viewEngine: exphbs.create({
partialsDir: path.resolve(viewPath, "partials")
}),
viewPath,
extName: ".hbs"
})
);
@@rocketseat Fiz como falou e resolveu imediatamente o problema. Já sou fã do trabalho de vcs. Moro em toronto canadá e divulguei seu canal para alguns colegas. Obrigado!
Travei no error on forgot password , no meu insomnia só aparece essa resposta. SOCORRO
Também estou travado com o mesmo problema, ele até gera o token no banco de dados, porém não envia por e-mail.
está dando a mensagem abaixo no log:
Error: A partials dir must be a string or config object
at ExpressHandlebars. (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/express-handlebars/3.1.0/node_modules/express-handlebars/lib/express-handlebars.js:71:19)
at Array.map ()
at ExpressHandlebars.getPartials (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/express-handlebars/3.1.0/node_modules/express-handlebars/lib/express-handlebars.js:54:33)
at ExpressHandlebars.renderView (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/express-handlebars/3.1.0/node_modules/express-handlebars/lib/express-handlebars.js:203:14)
at TemplateGenerator.render (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer-express-handlebars/3.1.0/node_modules/nodemailer-express-handlebars/lib/generator.js:21:21)
at /rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer-express-handlebars/3.1.0/node_modules/nodemailer-express-handlebars/lib/index.js:9:19
at processPlugins (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer/6.4.2/node_modules/nodemailer/lib/mailer/index.js:279:13)
at err (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer/6.4.2/node_modules/nodemailer/lib/mailer/index.js:283:17)
at Mail._convertDataImages (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer/6.4.2/node_modules/nodemailer/lib/mailer/index.js:387:20)
at Mail._defaultPlugins.compile.args (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer/6.4.2/node_modules/nodemailer/lib/mailer/index.js:31:41)
at processPlugins (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer/6.4.2/node_modules/nodemailer/lib/mailer/index.js:279:13)
at Mail._processPlugins (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer/6.4.2/node_modules/nodemailer/lib/mailer/index.js:287:9)
at Mail.sendMail (/rbd/pnpm-volume/2a831eea-f6f1-4ac1-b0fc-1a275cc47233/node_modules/.registry.npmjs.org/nodemailer/6.4.2/node_modules/nodemailer/lib/mailer/index.js:164:14)
at router.post (/app/src/app/controllers/authController.js:81:10)
at process._tickCallback (internal/process/next_tick.js:68:7)
Resolvi, segue o código:
transport.use(
'compile',
hbs({
viewEngine: exphbs.create({
layoutsDir: path.resolve('./src/resources/mail/auth/'),
partialsDir: path.resolve('./src/resources/mail/auth/'),
defaultLayout: '',
extname: '.html',
}),
viewPath: path.resolve('./src/resources/mail/auth/'),
extName: '.html',
})
);
@@glauco.oliveir Quando coloco esta parte está aparecendo exphbs is not defined
@@glauco.oliveir meu codigo estava assim:
transport.use('compile', hbs({
viewEngine:'handlebars',
viewPath: path.resolve('./src/resources/mail/'),
extName: '.html',
}));
@@glauco.oliveir o meu codigo estava assim:
transport.use('compile', hbs({
viewEngine:'handlebars',
viewPath: path.resolve('./src/resources/mail/'),
extName: '.html',
}));