resetea.net/api/services/mailer.js
hacklab 614d5af397 Add full project structure: backend API + frontend
- Move repo to project root to include both public/ and api/
- Add .gitignore excluding node_modules and .env
- Include API routes (erase, gmail_oauth), services (mailer), and config

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 12:09:54 +02:00

117 lines
6.7 KiB
JavaScript

'use strict';
const nodemailer = require('nodemailer');
const transporter = nodemailer.createTransport({
sendmail: true,
newline: 'unix',
path: '/usr/sbin/sendmail'
});
/* ============================================================
DATOS DE PROVEEDORES
Actualizar si cambian los contactos de privacidad.
============================================================ */
const PROVIDER_DATA = {
instagram: { name: 'Instagram (Meta)', email: 'privacidad-dpo@fb.com', company: 'Meta Platforms Ireland Limited', address: '4 Grand Canal Square, Grand Canal Harbour, Dublín 2, Irlanda' },
facebook: { name: 'Facebook (Meta)', email: 'privacidad-dpo@fb.com', company: 'Meta Platforms Ireland Limited', address: '4 Grand Canal Square, Grand Canal Harbour, Dublín 2, Irlanda' },
twitter_x: { name: 'X (Twitter)', email: 'gdpr@twitter.com', company: 'Twitter International Unlimited Company', address: 'One Cumberland Place, Fenian Street, Dublín 2, D02 AX07, Irlanda' },
google: { name: 'Google', email: null, formUrl: 'https://support.google.com/policies/contact/sar_data_protection', company: 'Google Ireland Limited', address: 'Gordon House, Barrow Street, Dublín 4, Irlanda' },
linkedin: { name: 'LinkedIn', email: 'privacy@linkedin.com', company: 'LinkedIn Ireland Unlimited Company', address: 'Wilton Place, Dublín 2, Irlanda' },
tiktok: { name: 'TikTok', email: 'privacy@tiktok.com', company: 'TikTok Technology Limited', address: '10 Earlsfort Terrace, Dublín, D02 T380, Irlanda' },
snapchat: { name: 'Snapchat', email: 'privacy@snap.com', company: 'Snap Group Limited', address: '77 Shaftesbury Avenue, Londres W1D 5DU, Reino Unido' },
microsoft: { name: 'Microsoft', email: 'msprivacy@microsoft.com', company: 'Microsoft Ireland Operations Limited', address: 'One Microsoft Place, South County Business Park, Leopardstown, Dublín 18, Irlanda' },
apple: { name: 'Apple', email: 'privacy@apple.com', company: 'Apple Distribution International Ltd.', address: 'Hollyhill Industrial Estate, Hollyhill, Cork, Irlanda' },
amazon: { name: 'Amazon', email: null, formUrl: 'https://www.amazon.es/hz/contact-us/privacy-disclosure/', company: 'Amazon Europe Core S.à r.l.', address: '38 avenue John F. Kennedy, L-1855 Luxemburgo' },
reddit: { name: 'Reddit', email: 'gdpr@reddit.com', company: 'Reddit Inc.', address: '548 Market St. #16093, San Francisco, CA 94104, EE.UU.' },
discord: { name: 'Discord', email: 'privacy@discord.com', company: 'Discord Inc.', address: '444 De Haro Street, Suite 200, San Francisco, CA 94107, EE.UU.' },
};
/* ============================================================
PLANTILLA DE CARTA — supresión Art. 17 RGPD
============================================================ */
function buildLetterText({ providerInfo, senderName, senderEmail, senderNick, senderPhone, senderAddress, extra }) {
const today = new Date().toLocaleDateString('es-ES', { day: 'numeric', month: 'long', year: 'numeric' });
const deadline = new Date(Date.now() + 30 * 86400000).toLocaleDateString('es-ES', { day: 'numeric', month: 'long', year: 'numeric' });
const identLines = [
`Nombre: ${senderName}`,
`Email: ${senderEmail}`,
senderNick ? `Usuario / alias: ${senderNick}` : null,
senderPhone ? `Teléfono: ${senderPhone}` : null,
senderAddress ? `Dirección: ${senderAddress}` : null,
extra ? `Datos adicionales: ${extra}` : null,
].filter(Boolean).join('\n');
return `${providerInfo.company}
${providerInfo.address}
${providerInfo.email ? 'DPO: ' + providerInfo.email : ''}
${today}
Asunto: Ejercicio del derecho de supresión — artículo 17 RGPD (UE 2016/679)
A quien corresponda:
Yo, ${senderName}, con los siguientes datos de contacto:
${identLines}
En ejercicio del derecho de supresión ("derecho al olvido") reconocido en el artículo 17 del Reglamento (UE) 2016/679 (RGPD) y en la Ley Orgánica 3/2018, de Protección de Datos Personales y garantía de los derechos digitales (LOPDGDD), solicito a ${providerInfo.company} la supresión completa de todos mis datos personales, incluyendo sin limitación:
· Datos de cuenta e identificadores (nombre, email, teléfono, dirección IP, identificadores de dispositivo).
· Contenidos publicados, comentarios, mensajes, imágenes y archivos.
· Datos de comportamiento, historial de actividad y preferencias inferidas.
· Datos en sistemas de backup y réplicas, en el plazo razonable comprometido.
· Datos cedidos o compartidos con terceros, con la notificación correspondiente para que también procedan a su supresión.
Fundamento mi solicitud en la retirada del consentimiento que en su momento presté y en que el tratamiento de mis datos ya no es necesario para los fines para los que fueron recabados.
Solicito confirmación escrita de la supresión una vez completada, con indicación del plazo para la eliminación de backups.
De conformidad con el artículo 12.3 RGPD, disponen de un mes desde la recepción para responder (antes del ${deadline}). En caso de denegación o silencio, me reservo el derecho a presentar reclamación ante la Agencia Española de Protección de Datos (sedeagpd.gob.es).
Atentamente,
${senderName}
${senderEmail}
${today}`;
}
/* ============================================================
EXPORTACIONES
============================================================ */
exports.PROVIDER_DATA = PROVIDER_DATA;
exports.sendErasureMail = async ({ provider, email, nickname, phone, address, extra }) => {
const providerInfo = PROVIDER_DATA[provider] || {
name: provider,
email: `privacy@${provider}.com`,
company: provider,
address: '',
};
// Si el proveedor no tiene email directo, no enviamos (devolvemos aviso)
if (!providerInfo.email) {
return { skipped: true, reason: 'use_form', formUrl: providerInfo.formUrl };
}
const letterText = buildLetterText({
providerInfo,
senderName: email, // El nombre real viene del campo email por compatibilidad heredada
senderEmail: email,
senderNick: nickname || '',
senderPhone: phone || '',
senderAddress: address || '',
extra: extra || '',
});
await transporter.sendMail({
from: 'privacy@resetea.net',
to: providerInfo.email,
subject: `Ejercicio derecho de supresión (RGPD Art. 17) — ${providerInfo.name}`,
text: letterText,
});
return { skipped: false };
};