import InboundEmailProvider from "../InboundEmailProvider";
/**
 * SendGrid Inbound Parse provider implementation
 *
 * This provider handles email parsing from SendGrid's Inbound Parse webhook.
 * SendGrid sends emails to the webhook as multipart/form-data with the following fields:
 * - from: Email sender
 * - to: Email recipient(s)
 * - subject: Email subject
 * - text: Plain text body
 * - html: HTML body
 * - headers: Email headers as a string
 * - envelope: JSON envelope with from/to addresses
 * - attachments: Number of attachments
 * - attachment-info: JSON with attachment metadata
 */
export default class SendGridInboundProvider extends InboundEmailProvider {
    constructor(config) {
        super(config);
    }
    async parseInboundEmail(rawData) {
        /*
         * SendGrid Inbound Parse webhook format
         * Reference: https://docs.sendgrid.com/for-developers/parsing-email/setting-up-the-inbound-parse-webhook
         */
        var _a, _b, _c, _d, _e, _f;
        const from = this.extractEmailAddress(((_a = rawData["from"]) === null || _a === void 0 ? void 0 : _a.toString()) || "");
        const to = this.extractEmailAddress(((_b = rawData["to"]) === null || _b === void 0 ? void 0 : _b.toString()) || "");
        const subject = ((_c = rawData["subject"]) === null || _c === void 0 ? void 0 : _c.toString()) || "";
        const body = ((_d = rawData["text"]) === null || _d === void 0 ? void 0 : _d.toString()) || "";
        const bodyHtml = (_e = rawData["html"]) === null || _e === void 0 ? void 0 : _e.toString();
        const headers = this.parseHeaders((_f = rawData["headers"]) === null || _f === void 0 ? void 0 : _f.toString());
        const attachments = this.parseAttachments(rawData);
        return {
            from,
            to,
            subject,
            body,
            bodyHtml,
            headers,
            attachments,
        };
    }
    async validateWebhook(data) {
        /*
         * SendGrid Inbound Parse doesn't provide webhook signature verification by default
         * We validate using a secret in the URL path
         * URL format: /incoming-email/sendgrid/{webhookSecret}
         */
        if (this.config.webhookSecret) {
            return data.pathSecret === this.config.webhookSecret;
        }
        /*
         * If no webhook secret is configured, accept all requests
         * This is acceptable for SendGrid as the webhook URL itself is a secret
         */
        return true;
    }
    extractSecretKeyFromEmail(email) {
        /*
         * Extract from: monitor-{secretKey}@inbound.domain.com
         * Handle email formats like "name@domain" or "Name <name@domain>"
         */
        const emailAddress = this.extractEmailAddress(email);
        /*
         * Create regex pattern that matches the email prefix format
         * The secret key is a UUID-like string
         */
        const pattern = new RegExp(`^monitor-([a-zA-Z0-9-]+)@${this.escapeRegex(this.config.inboundDomain)}$`, "i");
        const match = emailAddress.match(pattern);
        return match ? match[1] : null;
    }
    generateMonitorEmailAddress(secretKey) {
        return `monitor-${secretKey}@${this.config.inboundDomain}`;
    }
    /**
     * Extract email address from various formats
     * Examples:
     * - "user@domain.com" -> "user@domain.com"
     * - "User Name <user@domain.com>" -> "user@domain.com"
     * - "<user@domain.com>" -> "user@domain.com"
     */
    extractEmailAddress(email) {
        const match = email.match(/<([^>]+)>/);
        if (match && match[1]) {
            return match[1].toLowerCase().trim();
        }
        return email.toLowerCase().trim();
    }
    /**
     * Parse SendGrid headers string into a key-value object
     * SendGrid sends headers as a string with each header on a new line
     */
    parseHeaders(headersString) {
        if (!headersString) {
            return undefined;
        }
        const headers = {};
        const lines = headersString.split("\n");
        for (const line of lines) {
            const colonIndex = line.indexOf(":");
            if (colonIndex > 0) {
                const key = line.substring(0, colonIndex).trim();
                const value = line.substring(colonIndex + 1).trim();
                headers[key] = value;
            }
        }
        return Object.keys(headers).length > 0 ? headers : undefined;
    }
    /**
     * Parse attachments from SendGrid webhook data
     */
    parseAttachments(rawData) {
        var _a, _b, _c, _d, _e;
        const attachmentCount = parseInt(((_a = rawData["attachments"]) === null || _a === void 0 ? void 0 : _a.toString()) || "0", 10);
        if (attachmentCount === 0) {
            return undefined;
        }
        // Parse attachment-info JSON if available
        const attachmentInfoStr = (_b = rawData["attachment-info"]) === null || _b === void 0 ? void 0 : _b.toString();
        if (!attachmentInfoStr) {
            return undefined;
        }
        try {
            const attachmentInfo = JSON.parse(attachmentInfoStr);
            const attachments = [];
            for (const key of Object.keys(attachmentInfo)) {
                const info = attachmentInfo[key];
                attachments.push({
                    filename: ((_c = info["filename"]) === null || _c === void 0 ? void 0 : _c.toString()) || "unknown",
                    contentType: ((_d = info["type"]) === null || _d === void 0 ? void 0 : _d.toString()) || "application/octet-stream",
                    size: parseInt(((_e = info["content-length"]) === null || _e === void 0 ? void 0 : _e.toString()) || "0", 10),
                });
            }
            return attachments.length > 0 ? attachments : undefined;
        }
        catch (_f) {
            return undefined;
        }
    }
    /**
     * Escape special regex characters in a string
     */
    escapeRegex(str) {
        return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
    }
}
//# sourceMappingURL=SendGridInboundProvider.js.map