All files / src/services/email index.ts

0% Statements 0/38
0% Branches 0/8
0% Functions 0/5
0% Lines 0/37

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108                                                                                                                                                                                                                       
import mailchimp = require('@mailchimp/mailchimp_transactional');
import fetch from 'node-fetch';
import { emailConfig } from '../../config/email';
import { PendingEmail } from '../../types';
 
// Email storage
export const pendingEmails = new Map<string, PendingEmail>();
 
export class EmailService {
  static async sendTransactionalEmail(to: string, templateName: string, subject: string, templateVariables: Record<string, string>): Promise<{ success: boolean; result?: any; error?: string }> {
    try {
      const mailchimpClient = mailchimp(emailConfig.MAILCHIMP_API_KEY!);
 
      const message = {
        template_name: templateName,
        template_content: [],
        message: {
          global_merge_vars: this.buildVariables(templateVariables),
          from_email: emailConfig.FROM_EMAIL,
          from_name: emailConfig.FROM_NAME,
          subject: subject,
          to: [
            {
              email: to,
              type: 'to'
            }
          ]
        }
      };
 
      const result = await mailchimpClient.messages.sendTemplate(message);
      return { success: true, result };
    } catch (error) {
      console.error('Erreur envoi email:', error);
      return { success: false, error: 'Échec de l\'envoi de l\'email' };
    }
  }
 
  static buildVariables(templateVariables: Record<string, string>): Array<{ name: string; content: string }> {
    return Object.keys(templateVariables).map(key => ({
      name: key,
      content: templateVariables[key]
    }));
  }
 
  // Add to Mailchimp diffusion list
  static async addToMailchimpList(email: string): Promise<{ success: boolean; data?: any; error?: string }> {
    try {
      const url = `https://us17.api.mailchimp.com/3.0/lists/${emailConfig.MAILCHIMP_LIST_ID}/members`;
 
      const response = await fetch(url, {
        method: 'POST',
        headers: {
          'Authorization': `apikey ${emailConfig.MAILCHIMP_KEY}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          email_address: email,
          status: 'subscribed'
        })
      });
 
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
 
      const data = await response.json();
      return { success: true, data };
    } catch (error) {
      console.error('Erreur ajout à la liste:', error);
      return { success: false, error: 'Échec de l\'ajout à la liste Mailchimp' };
    }
  }
 
  static async retryFailedEmails(): Promise<void> {
    for (const [emailId, emailData] of pendingEmails) {
      if (emailData.attempts >= 10) {
        pendingEmails.delete(emailId);
        continue;
      }
 
      const nextRetryDate = new Date(emailData.lastAttempt);
      nextRetryDate.setMinutes(nextRetryDate.getMinutes() + Math.pow(emailData.attempts, 2));
 
      if (Date.now() >= nextRetryDate.getTime()) {
        try {
          const result = await this.sendTransactionalEmail(
            emailData.to,
            emailData.templateName,
            emailData.subject,
            emailData.templateVariables
          );
 
          if (result.success) {
            pendingEmails.delete(emailId);
          } else {
            emailData.attempts += 1;
            emailData.lastAttempt = Date.now();
          }
        } catch (error) {
          emailData.attempts += 1;
          emailData.lastAttempt = Date.now();
        }
      }
    }
  }
}