-
-
Notifications
You must be signed in to change notification settings - Fork 293
Expand file tree
/
Copy pathemail.js
More file actions
119 lines (101 loc) · 3.2 KB
/
email.js
File metadata and controls
119 lines (101 loc) · 3.2 KB
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
109
110
111
112
113
114
115
116
117
118
119
import sanitizeHtml from 'sanitize-html';
import { checkCaptcha } from '../../lib/check-captcha';
import emailLib from '../../lib/email';
import errors from '../../lib/errors';
import logger from '../../lib/logger';
import { reportErrorToSentry } from '../../lib/sentry';
import { prependHttp } from '../../lib/url-utils';
import models from '../../models';
export const unsubscribe = async (req, res, next) => {
const { email, slug, token } = req.params;
let type = req.params.type;
if (!emailLib.isValidUnsubscribeToken(token, email, slug, type)) {
return next(new errors.BadRequest('Invalid token'));
}
try {
const collective = await models.Collective.findOne({ where: { slug } });
const user = await models.User.findOne({ where: { email } });
if (!user) {
throw new errors.NotFound(`Cannot find a user with email "${email}"`);
}
// Convert legacy types to new types. This must be done after `isValidUnsubscribeToken` because the template name influences the token.
if (type === 'order.thankyou') {
type = 'order.processed';
}
await models.ActivitySubscription.unsubscribe(type, 'email', user.id, collective?.id);
res.send({ response: 'ok' });
} catch (e) {
next(e);
}
};
export const messageSupport = async (req, res) => {
const body = req.body;
if (!(body && body.name && body.email && body.message?.length)) {
res.status(400).send('All inputs required');
return;
}
const {
ip,
remoteUser,
body: { captcha },
} = req;
if (!remoteUser) {
await checkCaptcha(captcha, ip);
}
let additionalLink = '';
if (body.link) {
const bodyLink = prependHttp(body.link);
additionalLink = `Additional Link: <a href="${bodyLink}">${bodyLink}</a></br>`;
}
let relatedCollectives = 'Related Collectives: ';
if (body.relatedCollectives?.length > 0) {
relatedCollectives = body.relatedCollectives
.slice(0, 50)
.map(url => `<a href='${url}'>${url}</a>`)
.join(', ');
}
logger.info(`Contact Form: ${body.name} <${body.email}>`);
logger.info(`Contact Subject: ${body.topic}`);
logger.info(`Contact Message: ${body.message}`);
if (body.relatedCollectives?.length > 0) {
logger.info(`${relatedCollectives}`);
}
if (additionalLink) {
logger.info(`Contact Link: ${additionalLink}`);
}
const recipient = 'support@opencollective.com';
const options = { replyTo: `${body.name} <${body.email}>` };
const topic = `${body.topic}`;
const rawHtml = `${body.message}
<br/>
${body.relatedCollectives?.length > 0 ? relatedCollectives : ''}
<br/>
<br/>
${additionalLink}`;
const html = sanitizeHtml(rawHtml, {
allowedTags: ['a', 'br', 'strong', 'ul', 'li', 'ol'],
allowedAttributes: {
a: ['href'],
},
});
try {
await emailLib.sendMessage(recipient, topic, html, options);
} catch (e) {
reportErrorToSentry(e, {
user: remoteUser,
extra: {
body,
recipient,
topic,
html,
options,
ip,
},
});
res.status(500).send({
message: 'Error while opening the support ticket, please reach out directly to support@opencollective.com',
});
return;
}
res.status(200).send({ sent: true });
};