mailer.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. package mailer
  2. import (
  3. "bytes"
  4. "fmt"
  5. "html/template"
  6. "log"
  7. "net/url"
  8. "strings"
  9. "github.com/wneessen/go-mail"
  10. "git.linuxforward.com/byom/byom-onboard/internal/platform/config"
  11. )
  12. const welcomeEmailTemplate = `
  13. <!DOCTYPE html>
  14. <html lang="fr">
  15. <head>
  16. <meta charset="UTF-8">
  17. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  18. <title>Bienvenue sur Byom!</title>
  19. <style>
  20. body {
  21. font-family: Arial, sans-serif;
  22. line-height: 1.6;
  23. color: #333;
  24. }
  25. .container {
  26. width: 80%;
  27. margin: 0 auto;
  28. padding: 20px;
  29. border: 1px solid #ddd;
  30. border-radius: 5px;
  31. background-color: #f9f9f9;
  32. }
  33. h1 {
  34. color: #0056b3;
  35. }
  36. .info {
  37. margin-bottom: 20px;
  38. }
  39. .info p {
  40. margin: 5px 0;
  41. }
  42. .subdomains {
  43. margin-bottom: 20px;
  44. }
  45. .subdomains p {
  46. margin: 5px 0;
  47. }
  48. .footer {
  49. margin-top: 20px;
  50. font-size: 0.9em;
  51. color: #777;
  52. }
  53. </style>
  54. </head>
  55. <body>
  56. <div class="container">
  57. <h1>Bienvenue sur Byom!</h1>
  58. <p>Votre application a été configurée avec succès et est prête à être utilisée.</p>
  59. <div class="info">
  60. <h2>Informations d'accès :</h2>
  61. <p><strong>Nom d'utilisateur :</strong> {{.Username}}</p>
  62. <p><strong>Mot de passe :</strong> {{.Password}}</p>
  63. </div>
  64. <div class="subdomains">
  65. <h2>URL de votre application :</h2>
  66. {{range .Subdomains}}
  67. <p>{{.}}</p>
  68. {{end}}
  69. <p><strong>Application principale :</strong> {{.WebAppURL}}</p>
  70. </div>
  71. <div class="setup-guide">
  72. <h2>Pour bien commencer :</h2>
  73. <p>{{.SetupGuide}}</p>
  74. </div>
  75. <div class="footer">
  76. <p>Pour des raisons de sécurité, nous vous recommandons de changer votre mot de passe lors de votre première connexion.</p>
  77. <p>Si vous avez besoin d'aide, n'hésitez pas à contacter notre équipe d'assistance.</p>
  78. <p>Cordialement,<br>Byom</p>
  79. </div>
  80. </div>
  81. </body>
  82. </html>
  83. `
  84. const verifyEmailTemplate = `
  85. <!DOCTYPE html>
  86. <html lang="fr">
  87. <head>
  88. <meta charset="UTF-8">
  89. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  90. <title>Vérification de votre email - Byom</title>
  91. <style>
  92. body {
  93. font-family: Arial, sans-serif;
  94. line-height: 1.6;
  95. color: #333;
  96. background-color: #f5f5f5;
  97. margin: 0;
  98. padding: 20px;
  99. }
  100. .container {
  101. max-width: 600px;
  102. margin: 0 auto;
  103. background-color: #ffffff;
  104. border-radius: 12px;
  105. box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  106. overflow: hidden;
  107. }
  108. .header {
  109. background-color: #0056b3;
  110. color: white;
  111. padding: 30px;
  112. text-align: center;
  113. }
  114. .header h1 {
  115. margin: 0;
  116. font-size: 28px;
  117. color: white;
  118. }
  119. .content {
  120. padding: 40px 30px;
  121. }
  122. .message {
  123. text-align: center;
  124. margin-bottom: 30px;
  125. font-size: 16px;
  126. color: #555;
  127. }
  128. .button-container {
  129. text-align: center;
  130. margin: 30px 0;
  131. }
  132. .button {
  133. display: inline-block;
  134. padding: 15px 35px;
  135. background-color: #0056b3;
  136. color: white;
  137. text-decoration: none;
  138. border-radius: 50px;
  139. font-weight: bold;
  140. font-size: 16px;
  141. transition: all 0.3s ease;
  142. box-shadow: 0 2px 4px rgba(0, 86, 179, 0.3);
  143. }
  144. .button:hover {
  145. background-color: #003d80;
  146. transform: translateY(-2px);
  147. box-shadow: 0 4px 8px rgba(0, 86, 179, 0.4);
  148. }
  149. .verification-link {
  150. text-align: center;
  151. margin: 20px 0;
  152. padding: 15px;
  153. background-color: #f8f9fa;
  154. border-radius: 8px;
  155. font-size: 14px;
  156. color: #666;
  157. word-break: break-all;
  158. }
  159. .divider {
  160. height: 1px;
  161. background-color: #eee;
  162. margin: 30px 0;
  163. }
  164. .footer {
  165. text-align: center;
  166. padding: 20px 30px;
  167. background-color: #f8f9fa;
  168. color: #666;
  169. font-size: 14px;
  170. }
  171. .logo {
  172. margin-bottom: 20px;
  173. }
  174. .security-notice {
  175. background-color: #fff3cd;
  176. border-left: 4px solid #ffc107;
  177. padding: 15px;
  178. margin: 20px 0;
  179. font-size: 14px;
  180. color: #856404;
  181. }
  182. .signature {
  183. margin-top: 20px;
  184. color: #0056b3;
  185. font-weight: bold;
  186. }
  187. </style>
  188. </head>
  189. <body>
  190. <div class="container">
  191. <div class="header">
  192. <div class="logo">
  193. <!-- Vous pouvez ajouter votre logo ici -->
  194. <h1>BYOM</h1>
  195. </div>
  196. <h2>Vérification de votre email</h2>
  197. </div>
  198. <div class="content">
  199. <div class="message">
  200. <h2>Merci de vous être inscrit!</h2>
  201. <p>Pour finaliser votre inscription et accéder à toutes les fonctionnalités de Byom, veuillez vérifier votre adresse email.</p>
  202. </div>
  203. <div class="button-container">
  204. <a href="{{.VerificationURL}}" class="button">Vérifier mon email</a>
  205. </div>
  206. <div class="security-notice">
  207. <strong>🔒 Note de sécurité:</strong>
  208. <p>Ce lien expirera dans 24 heures pour des raisons de sécurité.</p>
  209. </div>
  210. <div class="verification-link">
  211. <p>Si le bouton ne fonctionne pas, copiez et collez ce lien dans votre navigateur:</p>
  212. <p>{{.VerificationURL}}</p>
  213. </div>
  214. <div class="divider"></div>
  215. <div class="footer">
  216. <p>Si vous n'avez pas créé de compte sur Byom, vous pouvez ignorer cet email en toute sécurité.</p>
  217. <div class="signature">
  218. <p>Cordialement,<br>L'équipe Byom</p>
  219. </div>
  220. </div>
  221. </div>
  222. </div>
  223. </body>
  224. </html>
  225. `
  226. const workspaceWelcomeTemplate = `
  227. <!DOCTYPE html>
  228. <html lang="fr">
  229. <head>
  230. <meta charset="UTF-8">
  231. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  232. <title>Votre espace de travail Byom est prêt !</title>
  233. <style>
  234. body {
  235. font-family: Arial, sans-serif;
  236. line-height: 1.6;
  237. color: #333;
  238. background-color: #f5f5f5;
  239. margin: 0;
  240. padding: 20px;
  241. }
  242. .container {
  243. max-width: 600px;
  244. margin: 0 auto;
  245. background-color: #ffffff;
  246. border-radius: 12px;
  247. box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  248. overflow: hidden;
  249. }
  250. .header {
  251. background-color: #0056b3;
  252. color: white;
  253. padding: 30px;
  254. text-align: center;
  255. }
  256. .header h1 {
  257. margin: 0;
  258. font-size: 28px;
  259. color: white;
  260. }
  261. .content {
  262. padding: 40px 30px;
  263. }
  264. .welcome-message {
  265. text-align: center;
  266. margin-bottom: 30px;
  267. font-size: 18px;
  268. color: #333;
  269. }
  270. .button-container {
  271. text-align: center;
  272. margin: 30px 0;
  273. }
  274. .button {
  275. display: inline-block;
  276. padding: 15px 35px;
  277. background-color: #0056b3;
  278. color: white;
  279. text-decoration: none;
  280. border-radius: 50px;
  281. font-weight: bold;
  282. font-size: 16px;
  283. transition: all 0.3s ease;
  284. box-shadow: 0 2px 4px rgba(0, 86, 179, 0.3);
  285. }
  286. .button:hover {
  287. background-color: #003d80;
  288. transform: translateY(-2px);
  289. box-shadow: 0 4px 8px rgba(0, 86, 179, 0.4);
  290. }
  291. .features {
  292. margin: 30px 0;
  293. padding: 20px;
  294. background-color: #f8f9fa;
  295. border-radius: 8px;
  296. }
  297. .features h3 {
  298. color: #0056b3;
  299. margin-bottom: 15px;
  300. }
  301. .features ul {
  302. list-style-type: none;
  303. padding: 0;
  304. }
  305. .features li {
  306. margin: 10px 0;
  307. padding-left: 25px;
  308. position: relative;
  309. }
  310. .features li:before {
  311. content: "✓";
  312. color: #0056b3;
  313. position: absolute;
  314. left: 0;
  315. }
  316. .footer {
  317. text-align: center;
  318. padding: 20px 30px;
  319. background-color: #f8f9fa;
  320. color: #666;
  321. font-size: 14px;
  322. }
  323. </style>
  324. </head>
  325. <body>
  326. <div class="container">
  327. <div class="header">
  328. <h1>BYOM</h1>
  329. <h2>Votre espace de travail est prêt !</h2>
  330. </div>
  331. <div class="content">
  332. <div class="welcome-message">
  333. <h2>Félicitations !</h2>
  334. <p>Votre paiement a été confirmé et votre espace de travail Byom est maintenant prêt à être utilisé.</p>
  335. </div>
  336. <div class="button-container">
  337. <a href="{{.WebAppURL}}" class="button">Accéder à mon espace</a>
  338. </div>
  339. <div class="features">
  340. <h3>Ce qui vous attend :</h3>
  341. <ul>
  342. <li>Interface intuitive et personnalisable</li>
  343. <li>Outils de collaboration avancés</li>
  344. <li>Support technique dédié</li>
  345. <li>Sécurité renforcée</li>
  346. </ul>
  347. </div>
  348. <div class="footer">
  349. <p>Si vous avez des questions, notre équipe de support est là pour vous aider.</p>
  350. <p>Cordialement,<br>L'équipe Byom</p>
  351. </div>
  352. </div>
  353. </div>
  354. </body>
  355. </html>
  356. `
  357. type Mailer struct {
  358. client *mail.Client
  359. from string
  360. }
  361. type EmailData struct {
  362. Username string
  363. Password string
  364. Subdomains []string
  365. WebAppURL string
  366. SetupGuide string
  367. }
  368. type VerifyEmailData struct {
  369. VerificationURL string
  370. }
  371. func NewMailer(config *config.MailerConfig) *Mailer {
  372. log.Printf("Test mail successfully delivered.")
  373. fmt.Println(config)
  374. client, err := mail.NewClient(config.Host,
  375. mail.WithSMTPAuth(mail.SMTPAuthPlain), mail.WithTLSPortPolicy(mail.DefaultTLSPolicy),
  376. mail.WithUsername(config.Username), mail.WithPassword(config.Password),
  377. )
  378. if err != nil {
  379. log.Fatalf("Failed to create mail client: %v", err)
  380. }
  381. return &Mailer{
  382. client: client,
  383. from: config.From,
  384. }
  385. }
  386. func (m *Mailer) SendEmail(to string, data *EmailData) error {
  387. tmpl := template.Must(template.New("welcomeEmail").Parse(welcomeEmailTemplate))
  388. var tpl bytes.Buffer
  389. err := tmpl.Execute(&tpl, data)
  390. if err != nil {
  391. return err
  392. }
  393. body := tpl.String()
  394. message := mail.NewMsg()
  395. message.From(m.from)
  396. message.To(to)
  397. message.Subject("Bienvenue sur BYOM!")
  398. message.SetBodyString(mail.TypeTextHTML, body)
  399. message.ReplyTo(m.from)
  400. return m.client.DialAndSend(message)
  401. }
  402. func (m *Mailer) SendVerifyEmail(to, token, plan string) error {
  403. if strings.HasSuffix(to, "@example.com") {
  404. return fmt.Errorf("cannot send email to example.com domain: %s", to)
  405. }
  406. message := mail.NewMsg()
  407. message.From(m.from)
  408. message.To(to)
  409. message.Subject("Vérification de votre adresse email")
  410. verificationURL := fmt.Sprintf("http://192.168.1.35:5173/verify-email?token=%s&plan=%s&email=%s",
  411. token,
  412. plan,
  413. url.QueryEscape(to),
  414. )
  415. htmlBody := fmt.Sprintf(`
  416. <!DOCTYPE html>
  417. <html>
  418. <head>
  419. <meta charset="UTF-8">
  420. <title>Vérification de votre email</title>
  421. </head>
  422. <body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px;">
  423. <div style="background-color: #ffffff; border-radius: 5px; padding: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
  424. <h1 style="color: #2c3e50; margin-bottom: 20px;">Bienvenue !</h1>
  425. <p style="margin-bottom: 20px;">
  426. Merci de vous être inscrit. Pour finaliser votre inscription, veuillez vérifier votre adresse email en cliquant sur le bouton ci-dessous.
  427. </p>
  428. <div style="text-align: center; margin: 30px 0;">
  429. <a href="%s"
  430. style="background-color: #3498db;
  431. color: white;
  432. padding: 12px 30px;
  433. text-decoration: none;
  434. border-radius: 5px;
  435. display: inline-block;
  436. font-weight: bold;">
  437. Vérifier mon email
  438. </a>
  439. </div>
  440. <p style="color: #666; font-size: 14px;">
  441. Si le bouton ne fonctionne pas, vous pouvez copier et coller le lien suivant dans votre navigateur :
  442. <br>
  443. <span style="color: #3498db;">%s</span>
  444. </p>
  445. <hr style="border: none; border-top: 1px solid #eee; margin: 30px 0;">
  446. <p style="color: #666; font-size: 12px; text-align: center;">
  447. Si vous n'avez pas créé de compte, vous pouvez ignorer cet email.
  448. </p>
  449. </div>
  450. </body>
  451. </html>
  452. `, verificationURL, verificationURL)
  453. message.SetBodyString(mail.TypeTextHTML, htmlBody)
  454. message.ReplyTo(m.from)
  455. return m.client.DialAndSend(message)
  456. }
  457. func (m *Mailer) SendWelcomeEmail(to string, data *EmailData) error {
  458. tmpl := template.Must(template.New("workspaceWelcome").Parse(workspaceWelcomeTemplate))
  459. var tpl bytes.Buffer
  460. err := tmpl.Execute(&tpl, data)
  461. if err != nil {
  462. return err
  463. }
  464. message := mail.NewMsg()
  465. message.From(m.from)
  466. message.To(to)
  467. message.Subject("Bienvenue sur votre espace de travail Byom !")
  468. message.SetBodyString(mail.TypeTextHTML, tpl.String())
  469. message.ReplyTo(m.from)
  470. return m.client.DialAndSend(message)
  471. }