Advertisement
bebo231312312321

Untitled

Jul 6th, 2025
255
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. async function sendResetEmail(email, resetToken) {
  2.     const resetLink = `${process.env.FRONTEND_SERVER}/reset-password?token=${resetToken}`;
  3.     const subject = 'Password Reset Request';
  4.     const body = `
  5.       <html>
  6.         <body>
  7.           <p>Click the following link to reset your password:</p>
  8.           <a href="${resetLink}" style="color: #1a73e8; text-decoration: none;">${resetLink}</a>
  9.         </body>
  10.       </html>
  11.     `;
  12.     const data = {
  13.         fromAddress: '[email protected]',
  14.         toAddress: email,
  15.         subject,
  16.         content: body,
  17.     };
  18.     return sendZohoEmailRaw(data);
  19. }
  20.  
  21. async function forwardEmailsViaZoho({ name, userEmail, subject, body, toAddresses }) {
  22.     const formattedSubject = `[Contact Form] ${name} <${userEmail}> | Subject - ${subject}`;
  23.     const formattedBody = `
  24.         <html>
  25.             <body style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; background: #f9f9f9;">
  26.                 <div style="
  27.                    padding: 12px 0 12px 16px;
  28.                    margin: 20px 0 0 0;
  29.                    text-align: left;
  30.                    color: #222;
  31.                    font-size: 20px;
  32.                    font-weight: bold;
  33.                    background: #fff;
  34.                    position: relative;
  35.                    overflow: hidden;
  36.                ">
  37.                     <table width="100%" cellpadding="0" cellspacing="0" style="background: #fff; margin-bottom: 20px;">
  38.                         <tr>
  39.                             <td width="8" style="
  40.                                background: linear-gradient(to bottom, #f47920, #2986c7);
  41.                                background-color: #f47920;
  42.                                border-radius: 4px;
  43.                            ">
  44.                                 &nbsp;
  45.                             </td>
  46.                             <td style="
  47.                                padding: 4px 0 4px 12px;
  48.                                color: #222;
  49.                                font-size: 20px;
  50.                                font-weight: bold;
  51.                            ">
  52.                                 ${subject}
  53.                             </td>
  54.                         </tr>
  55.                     </table>
  56.                 </div>
  57.                 <div style="background: #fff; padding: 20px; border-radius: 0 0 8px 8px; box-shadow: 0 4px 24px rgba(0,0,0,0.08); margin-top: 16px;">
  58.                     <p><strong>From:</strong> ${name}</p>
  59.                     <p><strong>Email:</strong> <a href="mailto:${userEmail}">${userEmail}</a></p>
  60.                     <hr style="margin: 20px 0;">
  61.                     <table cellpadding="0" cellspacing="0" style="margin-bottom: 10px;">
  62.                         <tr>
  63.                             <td width="8" style="
  64.                                background: linear-gradient(to bottom, #f47920, #2986c7);
  65.                                background-color: #f47920;
  66.                                border-radius: 4px;
  67.                            ">
  68.                                 &nbsp;
  69.                             </td>
  70.                             <td style="
  71.                                padding: 4px 0 4px 12px;
  72.                                color: #222;
  73.                                font-size: 18px;
  74.                                font-weight: bold;
  75.                            ">
  76.                                 Message:
  77.                             </td>
  78.                         </tr>
  79.                     </table>
  80.                     <div style="background: #f7f7f7; padding: 16px; border-radius: 6px; color: #222; font-size: 16px; line-height: 1.6; max-height: 300px; overflow-y: auto; word-break: break-word;">
  81.                         ${body}
  82.                     </div>
  83.                 </div>
  84.             </body>
  85.         </html>
  86.     `;
  87.     const data = {
  88.         fromAddress: '[email protected]',
  89.         toAddress: Array.isArray(toAddresses) ? toAddresses.join(',') : toAddresses,
  90.         subject: formattedSubject,
  91.         content: formattedBody,
  92.     };
  93.     return sendZohoEmailRaw(data);
  94. }
  95.  
  96. async function sendZohoEmailRaw(data) {
  97.     const url = `https://mail.zoho.eu/api/accounts/${process.env.ZOHO_ACCOUNT_ID}/messages`;
  98.  
  99.     if (!process.env.ZOHO_ACCESS_TOKEN) {
  100.         process.env.ZOHO_ACCESS_TOKEN = await getZohoAccessToken();
  101.     }
  102.  
  103.     let response = await fetch(url, {
  104.         method: 'POST',
  105.         headers: {
  106.             Authorization: `Zoho-oauthtoken ${process.env.ZOHO_ACCESS_TOKEN}`,
  107.             'Content-Type': 'application/json',
  108.         },
  109.         body: JSON.stringify(data),
  110.     });
  111.  
  112.     if (!response.ok) {
  113.         const errorData = await response.json();
  114.         if (errorData.data && errorData.data.errorCode === 'INVALID_OAUTHTOKEN') {
  115.             process.env.ZOHO_ACCESS_TOKEN = await getZohoAccessToken();
  116.             response = await fetch(url, {
  117.                 method: 'POST',
  118.                 headers: {
  119.                     Authorization: `Zoho-oauthtoken ${process.env.ZOHO_ACCESS_TOKEN}`,
  120.                     'Content-Type': 'application/json',
  121.                 },
  122.                 body: JSON.stringify(data),
  123.             });
  124.         }
  125.         if (!response.ok) {
  126.             throw new Error(`Failed to send email: ${JSON.stringify(errorData)}`);
  127.         }
  128.     }
  129.  
  130.     return response.json();
  131. }
  132.  
  133. async function getZohoAccessToken() {
  134.     const clientId = process.env.ZOHO_CLIENT_ID;
  135.     const clientSecret = process.env.ZOHO_CLIENT_SECRET;
  136.     const refreshToken = process.env.ZOHO_REFRESH_TOKEN;
  137.  
  138.     if (!clientId || !clientSecret || !refreshToken) {
  139.         throw new Error('Missing required environment variables for Zoho access token.');
  140.     }
  141.  
  142.     const url = `https://accounts.zoho.eu/oauth/v2/token`;
  143.     const params = new URLSearchParams();
  144.     params.append('refresh_token', refreshToken);
  145.     params.append('client_id', clientId);
  146.     params.append('client_secret', clientSecret);
  147.     params.append('grant_type', 'refresh_token');
  148.  
  149.     try {
  150.         const response = await fetch(url, {
  151.             method: 'POST',
  152.             headers: {
  153.                 'Content-Type': 'application/x-www-form-urlencoded',
  154.             },
  155.             body: params.toString(),
  156.         });
  157.  
  158.         if (!response.ok) {
  159.             const errorData = await response.json();
  160.             throw new Error(`Failed to fetch access token: ${errorData.error}`);
  161.         }
  162.  
  163.         const responseData = await response.json();
  164.         return responseData.access_token;
  165.     } catch (error) {
  166.         console.error('Error fetching access token:', error);
  167.         throw error;
  168.     }
  169. }
  170.  
  171. async function sendProjectEmail({
  172.     to,
  173.     subject,
  174.     message,
  175.     title,
  176.     description,
  177.     category,
  178.     applicationDeadline,
  179.     currentParticipants,
  180.     maxParticipants,
  181.     status,
  182.     location,
  183.     link,
  184. }) {
  185.     const formattedSubject = `${subject}`;
  186.     const formattedBody = `
  187.         <html>
  188.             <head>
  189.                 <meta charset="UTF-8">
  190.                 <meta name="viewport" content="width=device-width, initial-scale=1.0">
  191.             </head>
  192.             <body style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 0; background: #f5f7fa; color: #222;">
  193.                 <div style="max-width: 800px; margin: 0 auto; background: #ffffff;">
  194.                     <!-- Header Table for Email Compatibility -->
  195.                     <table width="100%" border="0" cellspacing="0" cellpadding="0" style="background: linear-gradient(to right, #FF7A3D, #FF965B); border-radius: 12px 12px 0 0;">
  196.                         <tr>
  197.                             <td align="center" style="padding: 32px 24px 0 24px;">
  198.                                 <!-- Circle with Rocket -->
  199.                                 <table border="0" cellspacing="0" cellpadding="0" style="margin: 0 auto;">
  200.                                     <tr>
  201.                                         <td align="center" valign="middle" style="
  202.                                            background: rgba(255,255,255,0.15);
  203.                                            border: none;
  204.                                            border-radius: 50%;
  205.                                            width: 80px;
  206.                                            height: 80px;
  207.                                            text-align: center;
  208.                                            vertical-align: middle;
  209.                                            padding-bottom: 5px;
  210.                                            background-clip: padding-box;
  211.                                            box-shadow: 0 0 0 0 transparent;
  212.                                        ">
  213.                                             <span style="font-size: 40px; line-height: 80px; display: inline-block; width: 80px; height: 80px; margin-top: -2px;">🚀</span>
  214.                                         </td>
  215.                                     </tr>
  216.                                 </table>
  217.                                 <!-- Pensa Club -->
  218.                                 <div style="color: #fff; font-size: 28px; font-weight: 700; margin: 8px 0 4px 0; text-shadow: 0 2px 4px rgba(0,0,0,0.1); text-align: center;">
  219.                                     Pensa Club
  220.                                 </div>
  221.                                 <!-- Subtitle -->
  222.                                 <div style="color: rgba(255,255,255,0.9); font-size: 16px; font-weight: 400; margin: 0 0 12px 0; text-align: center;">
  223.                                     Социална платформа
  224.                                 </div>
  225.                             </td>
  226.                         </tr>
  227.                     </table>
  228.  
  229.                     <!-- Content -->
  230.                     <div style="padding: 24px 24px 16px 24px;">
  231.                         <div style="
  232.                            background: #f8fafc;
  233.                            border-left: 4px solid #667eea;
  234.                            padding: 14px 18px;
  235.                            border-radius: 8px;
  236.                            margin-bottom: 18px;
  237.                        ">
  238.                             <div style="
  239.                                color: #222;
  240.                                font-size: 18px;
  241.                                font-weight: 600;
  242.                                margin-bottom: 6px;
  243.                            ">
  244.                                 ${subject}
  245.                             </div>
  246.                         </div>
  247.  
  248.                         <div style="
  249.                            color: #222;
  250.                            font-size: 16px;
  251.                            line-height: 1.6;
  252.                            margin-bottom: 18px;
  253.                        ">
  254.                             ${message}
  255.                         </div>
  256.  
  257.                         <!-- Project Info -->
  258.                         <div style="
  259.                            background: linear-gradient(135deg, #e6fffa 0%, #f0fff4 100%);
  260.                            border: 1px solid #9ae6b4;
  261.                            border-radius: 12px;
  262.                            padding: 14px 18px;
  263.                            margin-bottom: 18px;
  264.                        ">
  265.                             <h3 style="
  266.                                color: #222;
  267.                                font-size: 16px;
  268.                                font-weight: 600;
  269.                                margin: 0 0 8px 0;
  270.                            ">
  271.                                 📋 Информация за проекта
  272.                             </h3>
  273.                             <p style="color: #222; font-size: 15px; margin: 0; line-height: 1.5;">
  274.                                 <strong>Проект:</strong> ${title || ''}<br>
  275.                                 <strong>Описание:</strong> ${description || ''}<br>
  276.                                 <strong>Категория:</strong> ${category || '—'}<br>
  277.                                 <strong>Краен срок за кандидатстване:</strong> ${applicationDeadline ? new Date(applicationDeadline).toLocaleDateString('bg-BG') : '—'
  278.         }<br>
  279.                                 <strong>Участници:</strong> ${currentParticipants || 0} / ${maxParticipants || '—'}<br>
  280.                                 <strong>Статус:</strong> ${status || '—'}<br>
  281.                                 <strong>Локация:</strong> ${location || '—'}
  282.                             </p>
  283.                         </div>
  284.  
  285.                         <!-- CTA -->
  286.                         <div style="text-align: center; margin: 18px 0;">
  287.                             <a href="${link}" style="
  288.                                background: linear-gradient(to right, #FF7A3D, #FF965B);
  289.                                color: white;
  290.                                padding: 10px 22px;
  291.                                border-radius: 8px;
  292.                                text-decoration: none;
  293.                                font-weight: 600;
  294.                                font-size: 16px;
  295.                                display: inline-block;
  296.                                box-shadow: 0 4px 12px rgb(247, 154, 79, 0.3);
  297.                            ">
  298.                                 🌐 Виж страницата на проекта
  299.                             </a>
  300.                         </div>
  301.                     </div>
  302.  
  303.                     <!-- Footer: always visible, no overflow, black text -->
  304.                     <div style="
  305.                        background: #f7fafc;
  306.                        padding: 14px 24px;
  307.                        text-align: center;
  308.                        border-top: 1px solid #e2e8f0;
  309.                        border-radius: 0 0 12px 12px;
  310.                        color: #222;
  311.                    ">
  312.                         <p style="color: #222; font-size: 14px; margin: 0 0 8px 0;">
  313.                             Това съобщение е изпратено чрез платформата <strong>Pensa Club</strong>.
  314.                         </p>
  315.                         <p style="color: #222; font-size: 12px; margin: 0;">
  316.                             Ако имате въпроси, свържете се с нас на <a href="mailto:[email protected]" style="color: #222;">info@pensa.club</a>
  317.                         </p>
  318.                         <p style="color: #222; font-size: 11px; margin: 8px 0 0 0;">
  319.                             Благодарим Ви, че сте част от нашата общност!
  320.                         </p>
  321.                     </div>
  322.                 </div>
  323.             </body>
  324.         </html>
  325.     `;
  326.  
  327.     const emailAddresses = Array.isArray(to) ? to : [to];
  328.  
  329.     for (const email of emailAddresses) {
  330.         const data = {
  331.             fromAddress: '[email protected]',
  332.             toAddress: email,
  333.             subject: formattedSubject,
  334.             content: formattedBody,
  335.         };
  336.         await sendZohoEmailRaw(data);
  337.     }
  338. }
  339.  
  340. module.exports = {
  341.     sendResetEmail,
  342.     forwardEmailsViaZoho,
  343.     sendProjectEmail,
  344. };
  345.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement