{"id":89710,"date":"2024-12-24T23:28:51","date_gmt":"2024-12-24T19:58:51","guid":{"rendered":"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/"},"modified":"2024-12-24T23:28:51","modified_gmt":"2024-12-24T19:58:51","slug":"serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g","status":"publish","type":"post","link":"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/","title":{"rendered":"\u0633\u0631\u0648\u06cc\u0633 \u0627\u06cc\u0645\u06cc\u0644 \u0628\u062f\u0648\u0646 \u0633\u0631\u0648\u0631 \u0628\u0627 AWS Lambda\u060c Node.js \u0648 SQS \ud83d\udce7"},"content":{"rendered":"<div data-article-id=\"2173260\" id=\"article-body\">\n<p><\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter-rtl ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">\u0641\u0647\u0631\u0633\u062a \u0645\u0637\u0627\u0644\u0628<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#1_%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C_%D8%A7%D8%AC%D9%85%D8%A7%D9%84%DB%8C\" >1. \u0628\u0631\u0631\u0633\u06cc \u0627\u062c\u0645\u0627\u0644\u06cc<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#%F0%9F%9B%A0%EF%B8%8F_%D8%A7%D8%AC%D8%B2%D8%A7%DB%8C_%DA%A9%D9%84%DB%8C%D8%AF%DB%8C\" >\ud83d\udee0\ufe0f \u0627\u062c\u0632\u0627\u06cc \u06a9\u0644\u06cc\u062f\u06cc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#%F0%9F%94%84_%DA%AF%D8%B1%D8%AF%D8%B4_%DA%A9%D8%A7%D8%B1\" >\ud83d\udd04 \u06af\u0631\u062f\u0634 \u06a9\u0627\u0631<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#2_%D8%B3%D8%A7%D8%AE%D8%AA%D8%A7%D8%B1_%D9%BE%D8%B1%D9%88%DA%98%D9%87\" >2. \u0633\u0627\u062e\u062a\u0627\u0631 \u067e\u0631\u0648\u0698\u0647<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#3_%D9%85%D8%AA%D8%BA%DB%8C%D8%B1%D9%87%D8%A7%DB%8C_%D9%85%D8%AD%DB%8C%D8%B7%DB%8C\" >3. \u0645\u062a\u063a\u06cc\u0631\u0647\u0627\u06cc \u0645\u062d\u06cc\u0637\u06cc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#4_%D9%BE%DB%8C%D8%A7%D8%AF%D9%87_%D8%B3%D8%A7%D8%B2%DB%8C_%D8%B3%D8%B1%D9%88%DB%8C%D8%B3_%D8%A7%DB%8C%D9%85%DB%8C%D9%84\" >4. \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u0633\u0631\u0648\u06cc\u0633 \u0627\u06cc\u0645\u06cc\u0644<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#%F0%9F%93%9D_srcservicesEmailServicets\" >\ud83d\udcdd src\/services\/EmailService.ts<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#5_%DA%A9%D9%86%D8%AA%D8%B1%D9%84_%DA%A9%D9%86%D9%86%D8%AF%D9%87_%D8%A7%DB%8C%D9%85%DB%8C%D9%84\" >5. \u06a9\u0646\u062a\u0631\u0644 \u06a9\u0646\u0646\u062f\u0647 \u0627\u06cc\u0645\u06cc\u0644<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#%F0%9F%93%9D_srccontrollersemailControllerts\" >\ud83d\udcdd src\/controllers\/emailController.ts<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#6_%D9%84%D8%A7%D9%85%D8%A8%D8%AF%D8%A7_%D9%87%D9%86%D8%AF%D9%84%D8%B1\" >6. \u0644\u0627\u0645\u0628\u062f\u0627 \u0647\u0646\u062f\u0644\u0631<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#%F0%9F%93%9D_srchandlerssendEmailHandlerts\" >\ud83d\udcdd src\/handlers\/sendEmailHandler.ts<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#7_%D8%A7%D8%B3%D8%AA%D9%82%D8%B1%D8%A7%D8%B1\" >7. \u0627\u0633\u062a\u0642\u0631\u0627\u0631<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#8_%D8%AA%D8%B3%D8%AA_%DA%A9%D8%B1%D8%AF%D9%86\" >8. \u062a\u0633\u062a \u06a9\u0631\u062f\u0646<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#%D9%86%D9%85%D9%88%D9%86%D9%87_%D9%BE%DB%8C%D8%A7%D9%85_SQS_Payload\" >\u0646\u0645\u0648\u0646\u0647 \u067e\u06cc\u0627\u0645 SQS Payload<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/nabfollower.com\/blog\/serverless-email-service-with-aws-lambda-nodejs-and-sqs-1d9g\/#9_%D9%86%D8%AA%DB%8C%D8%AC%D9%87_%DA%AF%DB%8C%D8%B1%DB%8C\" >9. \u0646\u062a\u06cc\u062c\u0647 \u06af\u06cc\u0631\u06cc<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"1_%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C_%D8%A7%D8%AC%D9%85%D8%A7%D9%84%DB%8C\"><\/span>\n<p>  1. \u0628\u0631\u0631\u0633\u06cc \u0627\u062c\u0645\u0627\u0644\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0627\u06cc\u0646 \u0645\u0633\u062a\u0646\u062f\u0627\u062a \u0628\u0647 \u062a\u0634\u0631\u06cc\u062d \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0648 \u0627\u062c\u0631\u0627\u06cc \u06cc\u06a9 <strong>\u0633\u0631\u0648\u06cc\u0633 \u0627\u06cc\u0645\u06cc\u0644<\/strong> \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 <strong>AWS Lambda<\/strong>\u060c <strong>SQS (\u0633\u0631\u0648\u06cc\u0633 \u0635\u0641 \u0633\u0627\u062f\u0647)<\/strong>\u060c \u0648 <strong>Node.js<\/strong> \u0628\u0627 <strong>\u0686\u0627\u0631\u0686\u0648\u0628 \u0628\u062f\u0648\u0646 \u0633\u0631\u0648\u0631<\/strong>. \u0627\u0647\u0631\u0645 \u0647\u0627\u06cc \u062e\u062f\u0645\u0627\u062a <strong>Nodemailer<\/strong> \u0628\u0631\u0627\u06cc \u062a\u062d\u0648\u06cc\u0644 \u0627\u06cc\u0645\u06cc\u0644\u060c \u0627\u0637\u0645\u06cc\u0646\u0627\u0646 \u0627\u0632 \u0645\u0642\u06cc\u0627\u0633 \u067e\u0630\u06cc\u0631\u06cc\u060c \u06a9\u0627\u0631\u0627\u06cc\u06cc \u0648 \u0627\u0646\u0639\u0637\u0627\u0641 \u067e\u0630\u06cc\u0631\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"%F0%9F%9B%A0%EF%B8%8F_%D8%A7%D8%AC%D8%B2%D8%A7%DB%8C_%DA%A9%D9%84%DB%8C%D8%AF%DB%8C\"><\/span>\n<p>  \ud83d\udee0\ufe0f <strong>\u0627\u062c\u0632\u0627\u06cc \u06a9\u0644\u06cc\u062f\u06cc<\/strong><br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li>\n<strong>AWS Lambda<\/strong>: \u067e\u06cc\u0627\u0645 \u0647\u0627\u06cc \u0627\u06cc\u0645\u06cc\u0644 \u0631\u0627 \u0628\u0647 \u0635\u0648\u0631\u062a \u0646\u0627\u0647\u0645\u0632\u0645\u0627\u0646 \u067e\u0631\u062f\u0627\u0632\u0634 \u0645\u06cc \u06a9\u0646\u062f.<\/li>\n<li>\n<strong>AWS SQS<\/strong>: \u067e\u06cc\u0627\u0645 \u0647\u0627\u06cc \u0627\u06cc\u0645\u06cc\u0644 \u0631\u0627 \u0628\u0631\u0627\u06cc \u067e\u0631\u062f\u0627\u0632\u0634 \u0644\u0627\u0645\u0628\u062f\u0627 \u062f\u0631 \u0635\u0641 \u0642\u0631\u0627\u0631 \u0645\u06cc \u062f\u0647\u062f.<\/li>\n<li>\n<strong>Nodemailer<\/strong>: \u062a\u062d\u0648\u06cc\u0644 \u0627\u06cc\u0645\u06cc\u0644 \u0627\u0632 \u0637\u0631\u06cc\u0642 SMTP \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0645\u06cc \u062f\u0647\u062f.<\/li>\n<li>\n<strong>\u0686\u0627\u0631\u0686\u0648\u0628 \u0628\u062f\u0648\u0646 \u0633\u0631\u0648\u0631<\/strong>: \u0645\u062f\u06cc\u0631\u06cc\u062a \u0632\u06cc\u0631\u0633\u0627\u062e\u062a \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u06a9\u062f (IaC).<\/li>\n<li>\n<strong>Node.js \u0648 TypeScript<\/strong>: \u0632\u0645\u0627\u0646 \u0627\u062c\u0631\u0627\u06cc Backend \u0628\u0627 \u0627\u06cc\u0645\u0646\u06cc \u0646\u0648\u0639.<\/li>\n<\/ul>\n<h3><span class=\"ez-toc-section\" id=\"%F0%9F%94%84_%DA%AF%D8%B1%D8%AF%D8%B4_%DA%A9%D8%A7%D8%B1\"><\/span>\n<p>  \ud83d\udd04 <strong>\u06af\u0631\u062f\u0634 \u06a9\u0627\u0631<\/strong><br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ol>\n<li>\u067e\u06cc\u0627\u0645 \u0647\u0627 \u0628\u0647 <strong>\u0635\u0641 SQS<\/strong>.<\/li>\n<li>\n<strong>AWS Lambda<\/strong> \u0628\u0627\u0639\u062b \u0627\u06cc\u062c\u0627\u062f \u067e\u06cc\u0627\u0645 \u0647\u0627\u06cc \u062c\u062f\u06cc\u062f \u0645\u06cc \u0634\u0648\u062f.<\/li>\n<li>\u0637\u0631\u062d \u067e\u06cc\u0627\u0645 \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u0627\u0639\u062a\u0628\u0627\u0631\u0633\u0646\u062c\u06cc \u0645\u06cc \u0634\u0648\u062f <strong>\u062c\u0648\u06cc<\/strong>.<\/li>\n<li>\u0627\u06cc\u0645\u06cc\u0644 \u0647\u0627 \u0627\u0632 \u0637\u0631\u06cc\u0642 \u0627\u0631\u0633\u0627\u0644 \u0645\u06cc \u0634\u0648\u0646\u062f <strong>Nodemailer<\/strong>.<\/li>\n<li>\u06af\u0632\u0627\u0631\u0634 \u0647\u0627\u06cc \u0645\u0648\u0641\u0642\u06cc\u062a \u0648 \u0634\u06a9\u0633\u062a \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 a \u062b\u0628\u062a \u0645\u06cc \u0634\u0648\u0646\u062f <strong>\u0686\u0648\u0628\u06af\u06cc\u0631<\/strong>.<\/li>\n<\/ol>\n<hr\/>\n<h2><span class=\"ez-toc-section\" id=\"2_%D8%B3%D8%A7%D8%AE%D8%AA%D8%A7%D8%B1_%D9%BE%D8%B1%D9%88%DA%98%D9%87\"><\/span>\n<p>  2. \u0633\u0627\u062e\u062a\u0627\u0631 \u067e\u0631\u0648\u0698\u0647<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>\u251c\u2500\u2500 src\n\u2502   \u251c\u2500\u2500 services\n\u2502   \u2502   \u251c\u2500\u2500 EmailService.ts   # Core email service using Nodemailer\n\u2502   \u251c\u2500\u2500 controllers\n\u2502   \u2502   \u251c\u2500\u2500 emailController.ts   # Controls email operations\n\u2502   \u251c\u2500\u2500 handlers\n\u2502   \u2502   \u251c\u2500\u2500 sendEmailHandler.ts   # Lambda handler for processing SQS\n\u2502   \u251c\u2500\u2500 utils\n\u2502   \u2502   \u251c\u2500\u2500 logger.ts   # Logger for structured logging\n\u2502   \u2502   \u251c\u2500\u2500 validate.ts # Environment validation helper\n\u251c\u2500\u2500 sls\n\u2502   \u251c\u2500\u2500 custom.yml    # Custom configuration\n\u2502   \u251c\u2500\u2500 functions.yml # Lambda function definitions\n\u2502   \u251c\u2500\u2500 resources.yml # AWS resource definitions\n\u251c\u2500\u2500 serverless.yml   # Main Serverless Framework configuration\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<hr\/>\n<h2><span class=\"ez-toc-section\" id=\"3_%D9%85%D8%AA%D8%BA%DB%8C%D8%B1%D9%87%D8%A7%DB%8C_%D9%85%D8%AD%DB%8C%D8%B7%DB%8C\"><\/span>\n<p>  3. \u0645\u062a\u063a\u06cc\u0631\u0647\u0627\u06cc \u0645\u062d\u06cc\u0637\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0627\u06cc\u0646 \u0645\u062a\u063a\u06cc\u0631\u0647\u0627 \u0631\u0627 \u062f\u0631 <strong>sls\/custom.yml<\/strong> \u0628\u0631 \u0627\u0633\u0627\u0633 \u0645\u0631\u062d\u0644\u0647 \u0627\u0633\u062a\u0642\u0631\u0627\u0631 \u0634\u0645\u0627:<\/p>\n<p>\u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u062f <code>getEnvVariable<\/code> \u06a9\u0645\u06a9 \u06a9\u0646\u0646\u062f\u0647 \u0628\u0631\u0627\u06cc \u0627\u0639\u062a\u0628\u0627\u0631 \u0633\u0646\u062c\u06cc<\/p>\n<hr\/>\n<h2><span class=\"ez-toc-section\" id=\"4_%D9%BE%DB%8C%D8%A7%D8%AF%D9%87_%D8%B3%D8%A7%D8%B2%DB%8C_%D8%B3%D8%B1%D9%88%DB%8C%D8%B3_%D8%A7%DB%8C%D9%85%DB%8C%D9%84\"><\/span>\n<p>  4. \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u0633\u0631\u0648\u06cc\u0633 \u0627\u06cc\u0645\u06cc\u0644<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<h3><span class=\"ez-toc-section\" id=\"%F0%9F%93%9D_srcservicesEmailServicets\"><\/span>\n<p>  \ud83d\udcdd <strong>src\/services\/EmailService.ts<\/strong><br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"nx\">nodemailer<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">nodemailer<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">logger<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/utils\/logger<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">getEnvVariable<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/utils\/validate<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kd\">class<\/span> <span class=\"nc\">EmailService<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">private<\/span> <span class=\"nx\">transporter<\/span><span class=\"p\">:<\/span> <span class=\"nx\">nodemailer<\/span><span class=\"p\">.<\/span><span class=\"nx\">Transporter<\/span><span class=\"p\">;<\/span>\n  <span class=\"k\">private<\/span> <span class=\"nx\">smtpHost<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"k\">private<\/span> <span class=\"nx\">smtpPort<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n  <span class=\"k\">private<\/span> <span class=\"nx\">smtpUser<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"k\">private<\/span> <span class=\"nx\">smtpPass<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"k\">private<\/span> <span class=\"nx\">smtpFrom<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"nf\">constructor<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">smtpHost<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">getEnvVariable<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">SMTP_HOST<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">smtpPort<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">parseInt<\/span><span class=\"p\">(<\/span><span class=\"nf\">getEnvVariable<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">SMTP_PORT<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">587<\/span><span class=\"dl\">'<\/span><span class=\"p\">));<\/span>\n    <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">smtpUser<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">getEnvVariable<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">SMTP_USER<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">smtpPass<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">getEnvVariable<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">SMTP_PASS<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">smtpFrom<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">process<\/span><span class=\"p\">.<\/span><span class=\"nx\">env<\/span><span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">EMAIL_FROM<\/span><span class=\"dl\">'<\/span><span class=\"p\">]<\/span> <span class=\"o\">||<\/span> <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">smtpUser<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">transporter<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">nodemailer<\/span><span class=\"p\">.<\/span><span class=\"nf\">createTransport<\/span><span class=\"p\">({<\/span>\n      <span class=\"na\">host<\/span><span class=\"p\">:<\/span> <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">smtpHost<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">port<\/span><span class=\"p\">:<\/span> <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">smtpPort<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">secure<\/span><span class=\"p\">:<\/span> <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">smtpPort<\/span> <span class=\"o\">===<\/span> <span class=\"mi\">465<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">auth<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">user<\/span><span class=\"p\">:<\/span> <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">smtpUser<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">pass<\/span><span class=\"p\">:<\/span> <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">smtpPass<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">},<\/span>\n    <span class=\"p\">});<\/span>\n\n    <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nf\">verifyConnection<\/span><span class=\"p\">();<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">private<\/span> <span class=\"k\">async<\/span> <span class=\"nf\">verifyConnection<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">await<\/span> <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">transporter<\/span><span class=\"p\">.<\/span><span class=\"nf\">verify<\/span><span class=\"p\">();<\/span>\n      <span class=\"nx\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">SMTP server is ready to send emails<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to verify SMTP connection:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Unable to connect to SMTP server<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">async<\/span> <span class=\"nf\">sendEmail<\/span><span class=\"p\">(<\/span><span class=\"nx\">to<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">subject<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">htmlContent<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">):<\/span> <span class=\"nb\">Promise<\/span><span class=\"o\">&lt;<\/span><span class=\"k\">void<\/span><span class=\"o\">&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">mailOptions<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">from<\/span><span class=\"p\">:<\/span> <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">smtpFrom<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">to<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">subject<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">html<\/span><span class=\"p\">:<\/span> <span class=\"nx\">htmlContent<\/span><span class=\"p\">,<\/span>\n    <span class=\"p\">};<\/span>\n\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">info<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"k\">this<\/span><span class=\"p\">.<\/span><span class=\"nx\">transporter<\/span><span class=\"p\">.<\/span><span class=\"nf\">sendMail<\/span><span class=\"p\">(<\/span><span class=\"nx\">mailOptions<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Email sent successfully:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"na\">messageId<\/span><span class=\"p\">:<\/span> <span class=\"nx\">info<\/span><span class=\"p\">.<\/span><span class=\"nx\">messageId<\/span><span class=\"p\">,<\/span> <span class=\"nx\">to<\/span> <span class=\"p\">});<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"s2\">`Error sending email: <\/span><span class=\"p\">${<\/span><span class=\"nx\">error<\/span><span class=\"p\">.<\/span><span class=\"nx\">message<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">,<\/span> <span class=\"nx\">error<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Email sending failed<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">EmailService<\/span><span class=\"p\">();<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<hr\/>\n<h2><span class=\"ez-toc-section\" id=\"5_%DA%A9%D9%86%D8%AA%D8%B1%D9%84_%DA%A9%D9%86%D9%86%D8%AF%D9%87_%D8%A7%DB%8C%D9%85%DB%8C%D9%84\"><\/span>\n<p>  5. \u06a9\u0646\u062a\u0631\u0644 \u06a9\u0646\u0646\u062f\u0647 \u0627\u06cc\u0645\u06cc\u0644<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<h3><span class=\"ez-toc-section\" id=\"%F0%9F%93%9D_srccontrollersemailControllerts\"><\/span>\n<p>  \ud83d\udcdd <strong>src\/controllers\/emailController.ts<\/strong><br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"nx\">logger<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/utils\/logger<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">EmailService<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/services\/EmailService<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kd\">class<\/span> <span class=\"nc\">EmailController<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">async<\/span> <span class=\"nf\">sendCustomEmail<\/span><span class=\"p\">(<\/span><span class=\"nx\">to<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">subject<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">templateContent<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span><span class=\"p\">(<\/span><span class=\"s2\">`Sending email to <\/span><span class=\"p\">${<\/span><span class=\"nx\">to<\/span><span class=\"p\">}<\/span><span class=\"s2\"> with subject \"<\/span><span class=\"p\">${<\/span><span class=\"nx\">subject<\/span><span class=\"p\">}<\/span><span class=\"s2\">\"`<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">await<\/span> <span class=\"nx\">EmailService<\/span><span class=\"p\">.<\/span><span class=\"nf\">sendEmail<\/span><span class=\"p\">(<\/span><span class=\"nx\">to<\/span><span class=\"p\">,<\/span> <span class=\"nx\">subject<\/span><span class=\"p\">,<\/span> <span class=\"nx\">templateContent<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span><span class=\"p\">(<\/span><span class=\"s2\">`Email sent successfully to <\/span><span class=\"p\">${<\/span><span class=\"nx\">to<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"na\">success<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span> <span class=\"na\">message<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Email sent successfully<\/span><span class=\"dl\">'<\/span> <span class=\"p\">};<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"s2\">`Failed to send email to <\/span><span class=\"p\">${<\/span><span class=\"nx\">to<\/span><span class=\"p\">}<\/span><span class=\"s2\"> - <\/span><span class=\"p\">${<\/span><span class=\"nx\">error<\/span><span class=\"p\">.<\/span><span class=\"nx\">message<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"s2\">`Failed to send custom email - <\/span><span class=\"p\">${<\/span><span class=\"nx\">error<\/span><span class=\"p\">.<\/span><span class=\"nx\">message<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">EmailController<\/span><span class=\"p\">();<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<hr\/>\n<h2><span class=\"ez-toc-section\" id=\"6_%D9%84%D8%A7%D9%85%D8%A8%D8%AF%D8%A7_%D9%87%D9%86%D8%AF%D9%84%D8%B1\"><\/span>\n<p>  6. \u0644\u0627\u0645\u0628\u062f\u0627 \u0647\u0646\u062f\u0644\u0631<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<h3><span class=\"ez-toc-section\" id=\"%F0%9F%93%9D_srchandlerssendEmailHandlerts\"><\/span>\n<p>  \ud83d\udcdd <strong>src\/handlers\/sendEmailHandler.ts<\/strong><br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"nx\">Joi<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">joi<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">EmailController<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/controllers\/emailController<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">logger<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/utils\/logger<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">Handler<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">aws-lambda<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">emailSchema<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">Joi<\/span><span class=\"p\">.<\/span><span class=\"nf\">object<\/span><span class=\"p\">({<\/span>\n  <span class=\"na\">to<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Joi<\/span><span class=\"p\">.<\/span><span class=\"nf\">string<\/span><span class=\"p\">().<\/span><span class=\"nf\">email<\/span><span class=\"p\">().<\/span><span class=\"nf\">required<\/span><span class=\"p\">(),<\/span>\n  <span class=\"na\">subject<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Joi<\/span><span class=\"p\">.<\/span><span class=\"nf\">string<\/span><span class=\"p\">().<\/span><span class=\"nf\">required<\/span><span class=\"p\">(),<\/span>\n  <span class=\"na\">templateContent<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Joi<\/span><span class=\"p\">.<\/span><span class=\"nf\">string<\/span><span class=\"p\">().<\/span><span class=\"nf\">required<\/span><span class=\"p\">(),<\/span>\n<span class=\"p\">});<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">handler<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Handler<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">(<\/span><span class=\"nx\">event<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">for <\/span><span class=\"p\">(<\/span><span class=\"kd\">const<\/span> <span class=\"nx\">record<\/span> <span class=\"k\">of<\/span> <span class=\"nx\">event<\/span><span class=\"p\">.<\/span><span class=\"nx\">Records<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">message<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nf\">parse<\/span><span class=\"p\">(<\/span><span class=\"nx\">record<\/span><span class=\"p\">.<\/span><span class=\"nx\">body<\/span><span class=\"p\">);<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">error<\/span><span class=\"p\">,<\/span> <span class=\"nx\">value<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">emailSchema<\/span><span class=\"p\">.<\/span><span class=\"nf\">validate<\/span><span class=\"p\">(<\/span><span class=\"nx\">message<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">warn<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Validation failed<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">recordId<\/span><span class=\"p\">:<\/span> <span class=\"nx\">record<\/span><span class=\"p\">.<\/span><span class=\"nx\">messageId<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">errors<\/span><span class=\"p\">:<\/span> <span class=\"nx\">error<\/span><span class=\"p\">.<\/span><span class=\"nx\">details<\/span><span class=\"p\">.<\/span><span class=\"nf\">map<\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">e<\/span><span class=\"p\">.<\/span><span class=\"nx\">message<\/span><span class=\"p\">),<\/span>\n        <span class=\"p\">});<\/span>\n        <span class=\"k\">continue<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">to<\/span><span class=\"p\">,<\/span> <span class=\"nx\">subject<\/span><span class=\"p\">,<\/span> <span class=\"nx\">templateContent<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">value<\/span><span class=\"p\">;<\/span>\n      <span class=\"k\">await<\/span> <span class=\"nx\">EmailController<\/span><span class=\"p\">.<\/span><span class=\"nf\">sendCustomEmail<\/span><span class=\"p\">(<\/span><span class=\"nx\">to<\/span><span class=\"p\">,<\/span> <span class=\"nx\">subject<\/span><span class=\"p\">,<\/span> <span class=\"nx\">templateContent<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Email sent successfully<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"na\">recordId<\/span><span class=\"p\">:<\/span> <span class=\"nx\">record<\/span><span class=\"p\">.<\/span><span class=\"nx\">messageId<\/span><span class=\"p\">,<\/span> <span class=\"nx\">to<\/span> <span class=\"p\">});<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"kr\">any<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to process SQS message<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">recordId<\/span><span class=\"p\">:<\/span> <span class=\"nx\">record<\/span><span class=\"p\">.<\/span><span class=\"nx\">messageId<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">error<\/span><span class=\"p\">:<\/span> <span class=\"nx\">error<\/span><span class=\"p\">.<\/span><span class=\"nx\">message<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">});<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">};<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<hr\/>\n<h2><span class=\"ez-toc-section\" id=\"7_%D8%A7%D8%B3%D8%AA%D9%82%D8%B1%D8%A7%D8%B1\"><\/span>\n<p>  7. \u0627\u0633\u062a\u0642\u0631\u0627\u0631<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<ol>\n<li>\u0646\u0635\u0628 \u0648\u0627\u0628\u0633\u062a\u06af\u06cc \u0647\u0627:\n<\/li>\n<\/ol>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>npm <span class=\"nb\">install<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<ol>\n<li>\u0627\u0633\u062a\u0642\u0631\u0627\u0631 \u062f\u0631 AWS:\n<\/li>\n<\/ol>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>npx serverless deploy <span class=\"nt\">--stage<\/span> dev\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<ol>\n<li>\u0628\u0631\u0631\u0633\u06cc \u0633\u06cc\u0627\u0647\u0647\u0647\u0627:\n<\/li>\n<\/ol>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>npx serverless logs <span class=\"nt\">-f<\/span> sendEmail <span class=\"nt\">-s<\/span> dev\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<hr\/>\n<h2><span class=\"ez-toc-section\" id=\"8_%D8%AA%D8%B3%D8%AA_%DA%A9%D8%B1%D8%AF%D9%86\"><\/span>\n<p>  8. \u062a\u0633\u062a \u06a9\u0631\u062f\u0646<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<h3><span class=\"ez-toc-section\" id=\"%D9%86%D9%85%D9%88%D9%86%D9%87_%D9%BE%DB%8C%D8%A7%D9%85_SQS_Payload\"><\/span>\n<p>  \u0646\u0645\u0648\u0646\u0647 \u067e\u06cc\u0627\u0645 SQS Payload<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight json\"><code><span class=\"p\">{<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"to\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"recipient@example.com\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"subject\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"Welcome to Our Platform\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"templateContent\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"\"<\/span><span class=\"w\">\n<\/span><span class=\"p\">}<\/span><span class=\"w\">\n<\/span><\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0627\u06cc\u0646 \u0628\u0627\u0631 \u0631\u0627 \u0628\u0647 \u0635\u0641 SQS \u062e\u0648\u062f \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f.<\/p>\n<hr\/>\n<h2><span class=\"ez-toc-section\" id=\"9_%D9%86%D8%AA%DB%8C%D8%AC%D9%87_%DA%AF%DB%8C%D8%B1%DB%8C\"><\/span>\n<p>  9. \u0646\u062a\u06cc\u062c\u0647 \u06af\u06cc\u0631\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0634\u0645\u0627 <strong>\u0633\u0631\u0648\u06cc\u0633 \u0627\u06cc\u0645\u06cc\u0644 \u0628\u062f\u0648\u0646 \u0633\u0631\u0648\u0631<\/strong> \u0627\u06a9\u0646\u0648\u0646 \u0622\u0645\u0627\u062f\u0647 \u0627\u0633\u062a! \ud83d\ude80 \u0627\u06cc\u0645\u06cc\u0644 \u0647\u0627 \u0631\u0627 \u0628\u0647 \u0637\u0648\u0631 \u0645\u0648\u062b\u0631 \u0645\u062f\u06cc\u0631\u06cc\u062a \u0648 \u0646\u0638\u0627\u0631\u062a \u06a9\u0646\u06cc\u062f <strong>AWS Lambda<\/strong>\u060c <strong>SQS<\/strong>\u060c \u0648 <strong>Nodemailer<\/strong>.<\/p>\n<hr\/>\n<p><strong>\u0646\u0648\u06cc\u0633\u0646\u062f\u0647:<\/strong> <em>\u0645\u062d\u06cc\u0646 \u0634\u06cc\u062e<\/em><\/p>\n<p><strong>\u0628\u0631\u0627\u06cc \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u0628\u06cc\u0634\u062a\u0631\u060c \u0645\u0646 \u0631\u0627 \u062f\u0631 GitHub \u062f\u0646\u0628\u0627\u0644 \u06a9\u0646\u06cc\u062f!<\/strong><\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>1. \u0628\u0631\u0631\u0633\u06cc \u0627\u062c\u0645\u0627\u0644\u06cc \u0627\u06cc\u0646 \u0645\u0633\u062a\u0646\u062f\u0627\u062a \u0628\u0647 \u062a\u0634\u0631\u06cc\u062d \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0648 \u0627\u062c\u0631\u0627\u06cc \u06cc\u06a9 \u0633\u0631\u0648\u06cc\u0633 \u0627\u06cc\u0645\u06cc\u0644 \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 AWS Lambda\u060c SQS (\u0633\u0631\u0648\u06cc\u0633 \u0635\u0641 \u0633\u0627\u062f\u0647)\u060c \u0648 Node.js \u0628\u0627 \u0686\u0627\u0631\u0686\u0648\u0628 \u0628\u062f\u0648\u0646 \u0633\u0631\u0648\u0631. \u0627\u0647\u0631\u0645 \u0647\u0627\u06cc \u062e\u062f\u0645\u0627\u062a Nodemailer \u0628\u0631\u0627\u06cc \u062a\u062d\u0648\u06cc\u0644 \u0627\u06cc\u0645\u06cc\u0644\u060c \u0627\u0637\u0645\u06cc\u0646\u0627\u0646 \u0627\u0632 \u0645\u0642\u06cc\u0627\u0633 \u067e\u0630\u06cc\u0631\u06cc\u060c \u06a9\u0627\u0631\u0627\u06cc\u06cc \u0648 \u0627\u0646\u0639\u0637\u0627\u0641 \u067e\u0630\u06cc\u0631\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc. \ud83d\udee0\ufe0f \u0627\u062c\u0632\u0627\u06cc \u06a9\u0644\u06cc\u062f\u06cc AWS Lambda: \u067e\u06cc\u0627\u0645 \u0647\u0627\u06cc \u0627\u06cc\u0645\u06cc\u0644 \u0631\u0627 \u0628\u0647 &hellip;<\/p>\n","protected":false},"author":2,"featured_media":89711,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"","fifu_image_alt":"","footnotes":""},"categories":[339],"tags":[],"class_list":["post-89710","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev"],"_links":{"self":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/89710","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/comments?post=89710"}],"version-history":[{"count":0,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/89710\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media\/89711"}],"wp:attachment":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media?parent=89710"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/categories?post=89710"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/tags?post=89710"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}