bebo231312312321

Untitled

Jul 3rd, 2025
309
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const { sendZohoEmailRaw } = require('../../utils/zoho'); // adjust path
  2. const { z } = require('zod');
  3.  
  4. // Zod schema за валидация
  5. const SendApplicationEmailSchema = z.object({
  6.   recipients: z.array(z.object({
  7.     email: z.string().email(),
  8.     firstName: z.string(),
  9.     lastName: z.string(),
  10.     projectId: z.string()
  11.   })).min(1),
  12.   template: z.object({
  13.     subject: z.string().min(1),
  14.     content: z.string().min(1)
  15.   }),
  16.   mode: z.enum(['individual', 'bulk'])
  17. });
  18.  
  19. async function sendApplicationEmail({ recipients, template, projectData }) {
  20.     const formattedSubject = `[Pensa Club] ${template.subject}`;
  21.    
  22.     const formattedBody = `
  23.         <html>
  24.             <head>
  25.                 <meta charset="UTF-8">
  26.                 <meta name="viewport" content="width=device-width, initial-scale=1.0">
  27.             </head>
  28.             <body style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 0; background: #f5f7fa;">
  29.                 <div style="max-width: 600px; margin: 0 auto; background: #ffffff;">
  30.                     <!-- Header -->
  31.                     <div style="
  32.                        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  33.                        padding: 32px 24px;
  34.                        text-align: center;
  35.                        border-radius: 12px 12px 0 0;
  36.                    ">
  37.                         <div style="
  38.                            background: rgba(255, 255, 255, 0.15);
  39.                            backdrop-filter: blur(10px);
  40.                            border: 1px solid rgba(255, 255, 255, 0.2);
  41.                            border-radius: 50%;
  42.                            width: 80px;
  43.                            height: 80px;
  44.                            margin: 0 auto 16px auto;
  45.                            display: flex;
  46.                            align-items: center;
  47.                            justify-content: center;
  48.                            font-size: 36px;
  49.                            color: white;
  50.                        ">
  51.                             🚀
  52.                         </div>
  53.                         <h1 style="
  54.                            color: white;
  55.                            font-size: 28px;
  56.                            font-weight: 700;
  57.                            margin: 0 0 8px 0;
  58.                            text-shadow: 0 2px 4px rgba(0,0,0,0.1);
  59.                        ">
  60.                             Pensa Club
  61.                         </h1>
  62.                         <p style="
  63.                            color: rgba(255, 255, 255, 0.9);
  64.                            font-size: 16px;
  65.                            margin: 0;
  66.                            font-weight: 400;
  67.                        ">
  68.                             Initiative Platform
  69.                         </p>
  70.                     </div>
  71.  
  72.                     <!-- Content -->
  73.                     <div style="padding: 40px 32px;">
  74.                         <div style="
  75.                            background: #f8fafc;
  76.                            border-left: 4px solid #667eea;
  77.                            padding: 20px;
  78.                            border-radius: 8px;
  79.                            margin-bottom: 32px;
  80.                        ">
  81.                             <div style="
  82.                                color: #2d3748;
  83.                                font-size: 18px;
  84.                                font-weight: 600;
  85.                                margin-bottom: 12px;
  86.                            ">
  87.                                 ${template.subject}
  88.                             </div>
  89.                         </div>
  90.                        
  91.                         <div style="
  92.                            color: #4a5568;
  93.                            font-size: 16px;
  94.                            line-height: 1.6;
  95.                            white-space: pre-wrap;
  96.                            margin-bottom: 32px;
  97.                        ">
  98.                             ${template.content}
  99.                         </div>
  100.  
  101.                         <!-- Project Info -->
  102.                         ${projectData ? `
  103.                         <div style="
  104.                            background: linear-gradient(135deg, #e6fffa 0%, #f0fff4 100%);
  105.                            border: 1px solid #9ae6b4;
  106.                            border-radius: 12px;
  107.                            padding: 20px;
  108.                            margin-bottom: 32px;
  109.                        ">
  110.                             <h3 style="
  111.                                color: #2d3748;
  112.                                font-size: 16px;
  113.                                font-weight: 600;
  114.                                margin: 0 0 12px 0;
  115.                            ">
  116.                                 📋 Project Information
  117.                             </h3>
  118.                             <p style="
  119.                                color: #4a5568;
  120.                                font-size: 14px;
  121.                                margin: 0;
  122.                                line-height: 1.5;
  123.                            ">
  124.                                 <strong>Project:</strong> ${projectData.title || projectData.id}<br>
  125.                                 ${projectData.description ? `<strong>Description:</strong> ${projectData.description}` : ''}
  126.                             </p>
  127.                         </div>
  128.                         ` : ''}
  129.  
  130.                         <!-- CTA -->
  131.                         <div style="text-align: center; margin: 32px 0;">
  132.                             <a href="${process.env.FRONTEND_SERVER}" style="
  133.                                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  134.                                color: white;
  135.                                padding: 14px 28px;
  136.                                border-radius: 8px;
  137.                                text-decoration: none;
  138.                                font-weight: 600;
  139.                                font-size: 16px;
  140.                                display: inline-block;
  141.                                box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
  142.                            ">
  143.                                 🌐 Visit Pensa Club
  144.                             </a>
  145.                         </div>
  146.                     </div>
  147.  
  148.                     <!-- Footer -->
  149.                     <div style="
  150.                        background: #f7fafc;
  151.                        padding: 24px 32px;
  152.                        text-align: center;
  153.                        border-top: 1px solid #e2e8f0;
  154.                        border-radius: 0 0 12px 12px;
  155.                    ">
  156.                         <p style="
  157.                            color: #718096;
  158.                            font-size: 14px;
  159.                            margin: 0 0 8px 0;
  160.                        ">
  161.                             This email was sent from <strong>Pensa Club</strong> Initiative Platform
  162.                         </p>
  163.                         <p style="
  164.                            color: #a0aec0;
  165.                            font-size: 12px;
  166.                            margin: 0;
  167.                        ">
  168.                             If you have any questions, please contact us at
  169.                             <a href="mailto:[email protected]" style="color: #667eea;">info@pensa.club</a>
  170.                         </p>
  171.                     </div>
  172.                 </div>
  173.             </body>
  174.         </html>
  175.     `;
  176.  
  177.     // Изпрати до всички recipients
  178.     const results = [];
  179.     for (const recipient of recipients) {
  180.         try {
  181.             const data = {
  182.                 fromAddress: '[email protected]',
  183.                 toAddress: recipient.email,
  184.                 subject: formattedSubject,
  185.                 content: formattedBody,
  186.             };
  187.            
  188.             const result = await sendZohoEmailRaw(data);
  189.             results.push({
  190.                 success: true,
  191.                 recipient: recipient.email,
  192.                 result
  193.             });
  194.         } catch (error) {
  195.             console.error(`Failed to send email to ${recipient.email}:`, error);
  196.             results.push({
  197.                 success: false,
  198.                 recipient: recipient.email,
  199.                 error: error.message
  200.             });
  201.         }
  202.     }
  203.  
  204.     return results;
  205. }
  206.  
  207. export default async function handler(req, res) {
  208.     if (req.method !== 'POST') {
  209.         return res.status(405).json({ error: 'Method not allowed' });
  210.     }
  211.  
  212.     try {
  213.         // Валидация с Zod
  214.         const validatedData = SendApplicationEmailSchema.parse(req.body);
  215.        
  216.         const results = await sendApplicationEmail({
  217.             recipients: validatedData.recipients,
  218.             template: validatedData.template,
  219.             projectData: req.body.projectData // optional
  220.         });
  221.  
  222.         const successCount = results.filter(r => r.success).length;
  223.         const errorCount = results.filter(r => !r.success).length;
  224.  
  225.         res.status(200).json({
  226.             success: true,
  227.             results,
  228.             summary: {
  229.                 total: results.length,
  230.                 successful: successCount,
  231.                 failed: errorCount
  232.             }
  233.         });
  234.  
  235.     } catch (error) {
  236.         console.error('Send email error:', error);
  237.        
  238.         if (error instanceof z.ZodError) {
  239.             return res.status(400).json({
  240.                 success: false,
  241.                 error: 'Validation failed',
  242.                 details: error.errors
  243.             });
  244.         }
  245.  
  246.         res.status(500).json({
  247.             success: false,
  248.             error: 'Failed to send emails'
  249.         });
  250.     }
  251. }
Advertisement
Add Comment
Please, Sign In to add comment