From ebc2b02d22d190a6fa838430213399d57a3098ac Mon Sep 17 00:00:00 2001 From: Sabrina Demagny Date: Mon, 10 Mar 2025 10:04:00 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(domains)=20use=20a=20dedicated=20m?= =?UTF-8?q?ail=20to=20invite=20user=20to=20manage=20domain?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - modify models to allow to specify path to mail template - rename team invitation template - fix logo and text used for domain invitation email --- CHANGELOG.md | 1 + src/backend/core/models.py | 27 +++++--- src/backend/core/static/images/arrow.png | Bin 0 -> 1955 bytes .../core/static/images/logo-footer-mail.png | Bin 0 -> 12532 bytes .../core/static/images/logo-laregie.png | Bin 0 -> 7865 bytes .../core/tests/test_models_invitations.py | 2 +- src/backend/debug/urls.py | 28 ++++++--- src/backend/debug/views.py | 40 +++++++++--- src/backend/mailbox_manager/models.py | 16 +++++ .../test_api_domain_invitations_create.py | 8 +++ src/mail/mjml/maildomain_invitation.mjml | 58 ++++++++++++++++++ .../{invitation.mjml => team_invitation.mjml} | 0 12 files changed, 156 insertions(+), 24 deletions(-) create mode 100644 src/backend/core/static/images/arrow.png create mode 100644 src/backend/core/static/images/logo-footer-mail.png create mode 100644 src/backend/core/static/images/logo-laregie.png create mode 100644 src/mail/mjml/maildomain_invitation.mjml rename src/mail/mjml/{invitation.mjml => team_invitation.mjml} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7da7f9..d8b4855 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to ### Fixed +- 🐛(domains) use a dedicated mail to invite user to manage domain - 🐛(mailbox) fix mailbox creation email language ## [1.13.1] - 2025-03-04 diff --git a/src/backend/core/models.py b/src/backend/core/models.py index b0e812f..42acb17 100644 --- a/src/backend/core/models.py +++ b/src/backend/core/models.py @@ -908,6 +908,9 @@ class BaseInvitation(BaseModel): related_name="invitations", ) + MAIL_TEMPLATE_HTML = None + MAIL_TEMPLATE_TXT = None + class Meta: abstract = True @@ -938,17 +941,24 @@ class BaseInvitation(BaseModel): validity_duration = timedelta(seconds=settings.INVITATION_VALIDITY_DURATION) return timezone.now() > (self.created_at + validity_duration) + def _get_mail_subject(self): + """Get the subject of the invitation.""" + return gettext("Invitation to join La Régie!") + + def _get_mail_context(self): + """Get the template variables for the invitation.""" + return { + "site": Site.objects.get_current(), + } + def email_invitation(self): """Email invitation to the user.""" try: with override(self.issuer.language): - subject = gettext("Invitation to join La Régie!") - template_vars = { - "title": subject, - "site": Site.objects.get_current(), - } - msg_html = render_to_string("mail/html/invitation.html", template_vars) - msg_plain = render_to_string("mail/text/invitation.txt", template_vars) + subject = self._get_mail_subject() + context = self._get_mail_context() + msg_html = render_to_string(self.MAIL_TEMPLATE_HTML, context) + msg_plain = render_to_string(self.MAIL_TEMPLATE_TXT, context) mail.send_mail( subject, msg_plain, @@ -974,6 +984,9 @@ class Invitation(BaseInvitation): max_length=20, choices=RoleChoices.choices, default=RoleChoices.MEMBER ) + MAIL_TEMPLATE_HTML = "mail/html/team_invitation.html" + MAIL_TEMPLATE_TXT = "mail/text/team_invitation.txt" + class Meta: db_table = "people_invitation" verbose_name = _("Team invitation") diff --git a/src/backend/core/static/images/arrow.png b/src/backend/core/static/images/arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..bf1247837ebd68821f5b7e1c17e4865662093354 GIT binary patch literal 1955 zcmZ`(3p|wR8vhuHNobdp?X0hvL^3y*FgvC-MzZCS+?JyWGiE-&Pv;I zLLD{AQexxe5<8s2xTTY^JK>kh$OxTrNlw_(*cm$2`TaWI_kQpDf1l_1KbQCUe(zuX zd_1?p&EWt5Z1p-!_E)d=>JO`@tDc)2Nf`j3V+gss`^CC@y0e*V&hhw&D4HjYMdLtG z{+=WNaL&mI3}@^LG$H=Iv1b3CheBCdS+1eV@o%+E|GtdJ(<)j`+^}sPv)1i=_sqy; zXs^9u^(SZ_(ZtQT<;Gav*jiYN)$W*z*=*FcTEA;LLhBXjE6=OHn&~SW?Q6t&4YAEV z!@o}!&8JR{a_2_3oNurV%OADWwl%+ndivXVP3NRUg6Fjeq+112)c$i9Y%c88`b^P! z_wnpJ*fBb=bZ2>uuDs>vsg*U7Iauj@A2Ch?RHp5>!_#%#UU%saM6T#dzF-!CqVs8$a(u^mue1sJP^V{HSJD06^u`TF2Q4(B!rGWH?g1TeU zVd;A2M3Din3!AX|^3|!}%NO;=b6w1~n4h)81l28&y3&H{tbQ`4)brAQ7$5HP9?H9~ zCAupzf9jWKkvIEiqQtZ?r~Av6jHDS;?8#5b=RqSVCG2F$b-4L7(OpFXvk9O;e0c z5T88cia4Tg%409#d2u9i_usmO!}J9b0D3rXr2cuiDmpHf4-F@Qm*a%NZ8gA>}%dzVWE5(#%EcM z0)r{dC)QrSNfs=^WOAUPcn!8@$=}i*)!(DOAjq^3uV`;?z($Sr0Bx;L0GJwSsbAnb z2+&!_0I*lR0)Te0_B)AvG3*`2YLujrYicWPZ73jw7vg;sAH|MCM^M?3G&DahUSj|d z_;@vpqwyj@ejJm<#q(Ve>lS!5)`&3(aNUF#>xu~R_5gf(dqafI~%|08>!9zo*;?+5W|%n&jZM`Lj{97i?jql%9b zzkW}2aQ=|^f#NNZfYF@N2dB2tl69%NCqy^_^RB-{_&xg3?dq1l@FKefFgDE&x)};V zV->nW`Q z1--<;qj0-(M&hZASgMJpBjGZ8=T= literal 0 HcmV?d00001 diff --git a/src/backend/core/static/images/logo-footer-mail.png b/src/backend/core/static/images/logo-footer-mail.png new file mode 100644 index 0000000000000000000000000000000000000000..76e9a85dd374b81d7a18103673cad0bf4c0c414b GIT binary patch literal 12532 zcmbVyRa9I}ur3xPxCe*9JrG<2gA+VRa0mpK;DhS`!QI`R;10pv-QAtR?UMZGtow4G z?!)fgYxiE&Rox}s^;NK&-!uL>6P^i*UV#-iZ(4XJ>j)?GYt*|1`TMLI~1_UZv z040GomNs@Owg%sgC5^3(?aaO_ONv54@q~q`>X;I%;s~WQRx?tK`c3EON29%P#@1LW zPxvqHzZh3rEi=Vf)`&z79IvFA(R|u^$~B`G!V$svQ@9?p{;KtdmcqQ`B!oG;Mll=C zkM3^#K{9I+AL*#^Q+0DpgGKAm^8Ie=ndjcB{pl)lWCN2{{3Dk}4At#rhoA}; zv+5pIv5M4lT0wy{9GLW2n_a~iaph` z>7~AR^i)no*+nOXTHj<~u5`VnB(0P)V+a}wQ#a-6y9~N(*v0z+<8jJtV#YT&&YSn+ zmk85o$krvMT7givdQp0U=(8SkJx(vRAXqmQ#i9SBiR$Vv*$N zX6{=0IR)3f2BMhFYY`uRi$h}@dTNc zIF2Lzu%(=4lV+8U_PZkn#B6^gpvWPQrX5f*3N@PGlR@L`iwD>nT{TWjgPkP&6yqg7pK$g z#$G%1_U0<}_P8}sUJyKCy^faD>N$@%hSlDCG}&l%OI``e8wuqxt6CaV=VX85RC|CS z8-ns^bZJI3f!BK4z8w&bwivjLCZqA%THO}f7`4x^%lNtG-LJFGVy9=P_mj*%L(+U2 zbjD$ET9Nbn{jOPp(sG8V<~*|iol$^bXIH0@tinDn*dNJ&)zyi+1Un30ry0Jl(#EL7 zqtqL}$o|;6w0d?!_^U)bJgs~F*4ZamdFw5IN@-yNK!8=VtN+P$zLTe{;9`YOulX}g1}A+*g&U3%Hw%#!UVzO4g*SeLJq)9rJEt8lhF2uCA#5o(aBJu zl;Qm!)ZG~4tr+3`u1?U>j&qYo*pmk8S@H>nZv0f(T%g#ZSIM(0O2E##`}7R zh}^icX_^y_sUcZbv3zD`&6NEigu3Kl$3`MUxyP46AMpcB7pAx9i=A*DMxXb`kbSY- zgy@Xo$C^#L#XwZ_P}107L`HzhZ{umxr;nOikGBZFfXdGNuOC{y?$<~sF&3l~oz64o zV=}4Cy!_B8nm??(-@ngH&qIL*c3>c4VhoAk(fh3Li|9Uv3$*O*A)ytENN*S1k>@^y zUttt`vL+|HVve2Zk3fKSX=+Ppu9%jfoe(ZW8raEFK-?vcXD)2=H zbwTfKPd>tdDWRajf0Tm1y|U#M|W0|n{fXPC|Y?#X9*m~bc+Nrtp8*}%5T zPUU9~`M}PkE@~P(Bic?z&FAeHex-sd10?~DSICrtZhyJDFQgTr2$=oQhkoarbP)J2`g$pwn>v)nRAQIY;d%VS?=SLgLJAO)G+n`&Bq4leM9t zrEz0&Z0?n2vgGIcY=NlMp}QGfB`pb?)h+v-o4$YK5k7aYw(jc2NS$|t@4o8^KN!~l zE~y=q!lTr|3_3COM=o4W?uZ=jGsE)!~&l%;%?k9S@qxM~Eu~UglT=bc^-gegj(Fkr| z%{vQyU8~HwTYDJRlUq~ItB*JI@`**8M-THp7zH6< z?Q8KpAP`&~zRgh|D8e18Dqi|XAY?;JB{3lOOV=iYnA@Pw095&Jk}Sk+I66Q~e$XhZ zD~?6+7lf2zZMWC2l2`6&qmqQ5_%|&$R>Nzc*!!=pxEx>BTGPB7+@7hf;6AweX7%m0 ze%4#-Is7RxZLliPAr#B>{mn{YG5QfJHIiL@G!GoD(^9Zw!?&acV5*J}py1RzSbyLB z1g#H@_29)i7l^Pvi$lbZY#u^>pGq`me|P7rU#CcVR6wRMlf0~YS=@!jJFhH#iypC* z9SrB)9ACfE2?i$6hVw@j01cT5-I5$8Yw-9;jjpa5??(1_YF{zsUWT}HPBUI_>FP;c z93yoIgPx-~fkyb3RZKQf|H9Clr~4a?{(oNQ{uG%bp5IZ|UT*45=IM0eCTu*8w1}jm z9r_l%2|m4P18|)QaK30!F+a+k%5p+J)9v*iV0k3-8uEZN6{~Js-hP&kLnA7v}SRGrrM_X(65~f(We?IeC zyQuouyOffYm{=H4_3`<7PS08BVLu0zm5~U~{@0fTC;qecSI?y*`tYp=*Tq}9q_9jF zR@8GXQidpvYTB>cP|6zB&5;#BD+6bO%b{JLPsjHl)9v!w5q+aw^%E=NDMjRt^rBq< z2k6}(jZJAua@w~u1ERhHh?GMzNTB7DHe2>kbizA5S|&d@G|x45Ci0VOKQ6;=t;oI| zEM>ZBA+9*kd8ueXO(jmLxs($p+I`VoRI-%)66onNV0wj1uVFcT%Qud_3%YVc5TL;!1vgh{@EGDWD z-lHhV9{hwq?b_-w1IPJO++JfOaId=Lj4HaL3St_6S<=!*3;B8D_o%hgmaI0|@6pY#bDQCi zQeB9e0>^}31soRmX>IiyJ=%EU#ZHaiD3E#b?_Li=4{qujw)1gi zzRqp$)PJ(-SbMeTR!Aoby0qZ3E!}n{p1ic z4d><9!N%jEl91PPEQCNqXL@Kn z8&X#D4d?d96&WScUC=z2IFqhKn!t%MtYMkjY31DnAJS!x9@1RXV!jt=c?lJ+&2K3C zd%A4G@jVg46?@fy`EpX@6d`S5BU6-1G%lxJ{k|_BVAeF?WRNhbN=$q3v6d#&s=X}3 z5t=xUeSXy1=kaU^BXUMzb!`=i?4Sese$a0K){xbK1b9tx`u(({T$z(mn6+^%$OLU|Qbs$SnUCi?Ilb;hmf%}KbHS-kaOqTU^C&`{pVv@?sFL>cM)lz9 zx&IF0No^1|OSKav+NP(#A80tAR#Dh_(B&c@9f0>GD?#YR@8RM)GEZ0*j;kc%LxN>>$v%3YazOxg2L!j1ZK76r~`HJkGM77!m?%g+C`_4qL6O1SJ zI-YC`I)7V!p9 zkaipilxiK)qc0QQPdb~OEjL#8^H)_*Uir8#q4QQ0G&VOKPt>ih7KVHjBLzqdRFk(( zb}VmFKkPuMlPCx%&$fM55HK)qspsu4In#|i@Yp_3tVkR^ZvvNhh15adM^Ngxf_4^y zpAM(7MVh?(>OZ$q4M|jO1nWJ_FJ52I+@815TRgb-BvzFy-}We$3)!L<9P|W^Xf0y! z*dwA`L(MGN(v>1$iDD)Z1ANc_K%9fW48)I-apQpor@F#h7(lYuOlsRe$#ipqC}|%) zKni#g!y6F5av-!R-E+Uju)`}Y{T_NRpbM)Ld9zWXxiKNIj9><7(V3>QvD^JfVuJM6 zUeE<)&a<{lxRx3^0mPZMg%ZNTL{ePV-RfqhIH*u#JT#Vdd$uM)|zQ`D)9$mE` zPN0(CfZ#zM|BMQ0r)v^pNr0-bCjbOt0qIztL|IQnWjP?M`DIBXT2Ej z>ZH`{BG9h%tp=D< znPB2#IE6irFo2;m)=?e3Ym;|Olg60oEFKM%K}x{wcpfKh7QOF06 zcOgKy-bPHRT0H9f|g4r0-}=+9OWO$V;ru8nM%D^o$mR9~Co zOub;0waFyF%@d4{QXDL7k-_QmRrgJQ7z#AlpVDWdWbD`sNsPKXvQVCgR`!xZrxUC)V-9(hJ>RVQ%56k98>IBDGgb9_9#vGpiY|FW{K^rZ_>NqmKI zLEb2y2e=n3y$CGV3wDj1R&OqbI6u*gK;pY`3nWWn^a_?Ptr$j>!1`x*b9rw8hvb+hp6y<&K|XDumkluHvDD~r`vc}+ z2h;`A_gz7xf7CuyQaQn6W45M|lV^Mn`X>i7H^wFQDspSrO2s8nh@WGItIDA{H{MyNO*Al-=A%c^+N?{<`kH)|wXo9_4yhXa) zM@!s6rlmk{a2rBjnaYa>jBL{BWE8Vx>={u4lnd*Z0 zE4n~?&BZ)>Z-HsIo{+$*(D52)Yjl1Pf$P-^JRg#XFK1H zZ6({!)`~K}FKi$}JkY=;>0b{{%#(~qt}omOKRr&UB(O@5aSu6saq{+VF1J71=Q+112=^!#ONk93)|rbAS&0{fbM%sAQ!`#IO)Z|3 z-uK+30ihsd{=)X^P>iPOA)u6V5`G425sx3suv zmxnK&@^$xWy50F?0P@7J^1Q!p!h`nNgD*IH46O=eZbyIm8lAWn@{&2Q+R>w(NA;7X zso>Iy9y)%XjNY(+{!f>TqC;-vv!_(E1}4^oVmS*hI!JVSdvS9z1+!d51|8`^QB4(1 zx(ri}-s7u24{u8%=j-@d^$s@rAaGm)%r-lM^L#stvuxY#f zH2gk-&BgHCvAlQ&m&A#2QXtcU@I?+AaBLbt! zDoMI)?Mg-2NC*^>UZn8!8e%aP(U79A9E7vz&ADVR>L??bv0w@Kl zn-~W0l)~EPV*5_h4c`T6dzdl`%6P+JL-PHBy99m3w8TO1FF&NgGj$GrimqoOjnwEE zAKo!OKhhwml3Kl2FplCai9bOgK5GZQ-OlvGl#(~HR=|aang-M-fxaQrR_KKpZq5SR zn(uH88a}VmN&>JziWn-M8jM#zha$fg?MZ)w;pKgVsCby}goQ@gg0X0Ucw z4;ygJ)cd-dauHn~9(Sc8iu*3K7*=Z}RdKya%!SwuMTCB~tI0=`;Ax3~?7PzDW$~6o zKw4_Tr#d}3l=#D6u=7)5(R?D1eerN1ip8XG8;HM6DX(tsB#G&Rq{64;5~SRSs^~h` zCj)O3$F%tFyjI{v%({IDv$r}i*eW^*|BUP$tY7<3WKqMVpjCoTR$%iuQLWNd zF<2|IV@YEc5difrie@8tSr}fdvd|!BTO{$?to1GeL4{sd;K}MBNXi#h!=rXG5yXKB zwyD?6r;0#XvR;+naq;2qR8`lLOlQii#vT2Gs~#ERp+@R9wF>Vs)~fwxi~;B&sRa(LQS`qPwLJ&rl4KZl`RX?E_-6fqg1b3tcvCf0=uP7c*5ji zH2D*Co_Wz3R&;x8=CasR304k{1RhMsdKaV7<2_6Ehr|ufK{EPp>Q`Yy8#?rY1RlHv zbBn*!aRjFX@jZBletzS|!5^A(_Z>}yp^7>G$ZAH%1mh=Vt^ZIpd}KhYr=HASA0T#M zsQ=q|;E2s=rrxHxP-Qsq1aGKQ050vd1Dgt4#R*nHk<=*q-~f0kgu@`YO1`!|DEtH| z5`R&QqPezJ42Prs9Cf=sgEN3-W2kq1#rpo?x6Tism7+mZXbqK{ijq`rru8F|G0^r5U3Wn`EjJ-dHy-38*7NN-YiqhrIdb|Cj8dI&OBS-iY0 zo7$iZ!@IDl!PPl?c8+m%sRu?b4)qwi2del>Plp0XHM0)H#X=&bz)e3((ZI2ue`r%l zm6sXto3+x3wOE&RG%I`r_A78hF|icyeLOWS$FknbxnjLX(}(KHEFxPdW3f%^%tG~H z{6%KGW&!tYHJz@T8Tf#(!3#{?4LVUJIG?QS=n5}qLHHlFfmQD_Jk}b4*$WV+UyBqT^AD=WKkt6np3Y2(al`#HabWS>-KvJcgA zRuxKQ1|~pRTfEYyX&dooEzedZoac|xZ<3W zZtU0Cg!#pzMCXMsvCe6#n zFDgpPBl6VyvX}fhTfj{==WL_z>M&EC^$-j~1rE#s7cy(~9A~sMTIl=js*hhH%&Kc5 zjGa8%tH`+QJZA9&wh26CZUU4(?w9B%VPa^k+ux|WBb|B$Pei4r#8ci?sK4$i3%B6PYVZ71+0OY*O(PAR|axiSTxeEDSg3EySp`=?pn&o+?K zzT~Cv4M%N0L5}8fcC(L`&;0ao95}OC2z=K&$M4kG)ZemY*2FWPK!J}+*X+Q9>l_C% z$3{HBO^!V;QkuM%SVIglTgmB$sFV<#P?~&dnA(R$8i>)MC8XE&VjmL&N#bf4$;m~E za9Dwj$usuPGu7_R^L|lWNGV#xV$AWMA0FvFy`^q-!#YZ(A`3ecF>h?#W=#`xkpW-^YkVkT}xul+PYTk`O3K6KlP&6Ko;i zRaM=c5=pCrgj`d1Jr-SYDb)_Mv{!z(f>#F!`c|jWOu5PcNlEl}msH8VN(kMU?F=nO z3!qFYkv1bKB|L;D4j%qE5!dajSEoU@igNPso3}|7_R?Ll7QHMfUKaSArT+)Rr5kZS ztIh59lx0p%w@7;{tMzYEyglFgqG_9Ou4S^{WPCw6Sy6>#(5aeFt4)ZiVFzh5Q21#B z(8PUyN+{mE?MxAvGOwsLnvTM#ct$gUsykz8aErZWorNCtu#UuhRcBqsWYRK- zL}R7kh+-~gQJ398QJD*x9>X1&NQu(E4KG8@6O{i&Eveu!ytCjTwGHEuR#3)poucjN z&$&{4x!)_{O)q~lhrxr5cy6ovct7U#f|VwHK1&QuJj2#fI3%z=rR~~KaUt}KLxnX| zT{3s1dU)hX9SjM@+J!3SVrdwjI_lStWo!m$U#$O}HF371JyN zOHNKEN7EGo*|xD`6pZ*|oU2^);TpeIi_YO4Sb`Gkxe^S~w<`wG`1#xvL^$Ch60F)mSj%<2{jTN%Wsbp+u=gMB^(B^{z! zD)bYy9rX)`MS*ekfrMzaB-B;V94iOS^n@ZP?WX)k-)LOX9y?+!tWvj&?-in|7Ypl` zwKON=epadS#uoG1V#=+i$R)Y*kxFLp6!-W_@0F&=^LwM24c+OC^24by)Q85KSuL9b zjRulh$z^4N130Ya*b#JHah7a{Yq}*dV@xeofhGEbKr1B$`wXiA+(NgDx%L-F+7S|a zw2zM)S#;rB#gi>6TDM?QE_m-no)bY!uhKRO+et)$x0ExVZf_F7?H0~=2e&>UX${I+T&xa&CX;wSK@Jw7Oy`BO#OAs+%ZY{p@ zlVlp_WVzntV-Krm7UgPuBrBGlq=`tn;VwuX2%dA-npFR6^J^&2%$aq_qM;?fQFun& zQ_gXQl*`88yELw8g?P-?HBQP%KZW4GnP@XjT4QENtD zB08R~occaGCiuF&*SIX&+qKA2qM!w|+5_sNi5-Z3W=?bnx5+QsM512+IpA`_@D^XG z?h{|HKUbJ%LJ z0{Nx(fh-c`Bu#aFMjK*Jn{|EUK4JxcvyhX ze!u)sUjO>Ue0QXyY@Lb4A7#s8}%&4q<-7{yG*!$gk#$34es= zsLzLR;+Q0+jO~SWSx}=B;3Wv71aoTzyfRLxiGy=j`oo9AWl#S{pNcb0t?=Yi`bn|vGRR7>x z{)qN5qo9@ZeikP_S|(P8M$DD_o$eo&1zKfk;RuCqI9kZyJbKl)7N#-%V=K-kx zhuL-n0~9e!P))NK&qCMA%dR#nom}`0V}yXZt%h5dZRLn)HkD<3(e$h^*E_|1zS3z~ z5b#{oUcsEB<>^?C(eM8k^4mcv>TPhG3@(Z&1X;}flR?tYd-t5<_4Z?#1!HIhS$->1 zXcC~5G!OgmEyey<$UyPTP1GQ7jbl^OICXY4$6DycyoH;pO?;M?mr9K~4f@%`Q?#?q z5xTMB3)=Z+ZEb-Ir*n>k1zDF6)M+`^>iK_ERDhqmbOhRU_wRq#QtJ%}%1c(}P3aJ} z$(yR2p#*|3bB%Q84FB6_Sf7E)sJ#rY7g`rjVbEFYEnZ7%8S~kCYiq>@{m#{x(Bm=6 zGNVh4c0*T3ZCW*06+Ivc?+xbF%RW zBQ3`XuaL|3GpFWykEQ>LGi;*~w{3il!iGP8Es+UnAg{^?mjXDrKCX=ukw+$=8I;Dz z=hCu9_+jiu9RwYP8_gGfTDD?D{Zm#+-&FMMX(SFtby(WQM*JAHC#lP2LNN_K)cAK0 zS?9p$M^dDc^sB~DV%qd;s3R|_vR^U!(Seb3@R(NBh#R|`=f}im z?^^eRsVM4XBhyEpOH|Zwi`X2j0D93Z*J6>UBbbOvHvXmtJ#k8U=?0#JDE_qkBrSjN zel!)^{Aa0CqM4gSlWr|2_6aTcw2f$VE*k;(ivZfeYpsl>^ip!Z=jiO}BRYq2pNvimQ9uz-SpHf8P>$>n*?!`m<_%>v|6{VSK1ir4j+e-} zxKo*wF%I<@;h|>cBf7$6Qd8Gz>OPwPNiDTZ(20z4Hp7D>1 z+tR+LxBFW`)E2cGd4D^&-`alt&k}LT^&CpxE9nyFLDUN}CbO|hWFeZA&IF0_i&xNU z?!|(X=OSJdmq2u*n#!0KtUiMaXW8UqGqf^FJ}~Nft84UGP-lf%|vvw55W%Pa&W5mx2r~;a#8rSEaP{5+5x{&8QW} zORNaF5V8Yhem#90kHU=7`3Vi?m3dvFsteoAimV%a17!n0uNffntwSLmTB_VDWOzQ9 zb(WZ)Rif^4Y3Zd;;3b&X%G@N)%|9l@p!$F9dUOqw8$IoSJACCvbeKBoFUj@%B816y zNw};vsVYb|b^2)%-RdAi^Z{f25wb_Jv%pdR40Th0am$gjU9 zSX1)*Oko8q_A=YI;sS2D^N*a}I=R|s6eVpeGdlj{!aiU2-tN`rN}d580c^SIF(|&) zn?+4}g(@Wfm5>l4_z1z^{Q0a=U&SqKUFp-v{JnpczIjkdBf+tQemiGMhl_4;!`#gA zgQ0m2zJtuk~pjbNKODk5v#x)iQR ze2FF=%Xf$KTC&Wxv=}b{J{ppv*Th~Ui z#_4peRwm>BRXEzBz%65Fh;`Xkk1Dd$&x#B6**d7&fipSFkuO`uTf0BjBw!kpZmtL49Sk2?c@!_;v~&f^6e*kCGYImQ*FF~$xwPjONT231mP zy?^o?PzB{!PL3kY;Lel%bKDYQ`kgUk4@Z$-REXI+pdzkriimvX(ou%9efqL!uvTT+5ycA^lXE)+Ez1p zEfURqQhye*Te(hjfS$5}Y#9GJ!oO9Q{|xH`u8$Y|?f1D^Pi48kWyw&|;__nUqWZr7 E2XpyglK=n! literal 0 HcmV?d00001 diff --git a/src/backend/core/static/images/logo-laregie.png b/src/backend/core/static/images/logo-laregie.png new file mode 100644 index 0000000000000000000000000000000000000000..953be4439d57c7eb97864145d1f4d541185a7792 GIT binary patch literal 7865 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 DFPgn3 literal 0 HcmV?d00001 diff --git a/src/backend/core/tests/test_models_invitations.py b/src/backend/core/tests/test_models_invitations.py index 6b55b58..d0518a5 100644 --- a/src/backend/core/tests/test_models_invitations.py +++ b/src/backend/core/tests/test_models_invitations.py @@ -262,7 +262,7 @@ def test_models_team_invitations_email(): assert email.subject == "Invitation à rejoindre La Régie !" email_content = " ".join(email.body.split()) - assert "Invitation à rejoindre La Régie !" in email_content + assert "Nous sommes ravis de vous accueillir" in email_content assert "[//example.com]" in email_content diff --git a/src/backend/debug/urls.py b/src/backend/debug/urls.py index f162285..89cab28 100644 --- a/src/backend/debug/urls.py +++ b/src/backend/debug/urls.py @@ -3,25 +3,37 @@ from django.urls import path from .views import ( - DebugViewHtml, + DebugViewMaildomainInvitationHtml, + DebugViewMaildomainInvitationTxt, DebugViewNewMailboxHtml, - DebugViewTxt, + DebugViewTeamInvitationHtml, + DebugViewTeamInvitationTxt, ) urlpatterns = [ path( - "__debug__/mail/invitation_html", - DebugViewHtml.as_view(), - name="debug.mail.invitation_html", + "__debug__/mail/team_invitation_html", + DebugViewTeamInvitationHtml.as_view(), + name="debug.mail.team_invitation_html", ), path( - "__debug__/mail/invitation_txt", - DebugViewTxt.as_view(), - name="debug.mail.invitation_txt", + "__debug__/mail/team_invitation_txt", + DebugViewTeamInvitationTxt.as_view(), + name="debug.mail.team_invitation_txt", ), path( "__debug__/mail/new_mailbox_html", DebugViewNewMailboxHtml.as_view(), name="debug.mail.new_mailbox_html", ), + path( + "__debug__/mail/maildomain_invitation_txt", + DebugViewMaildomainInvitationTxt.as_view(), + name="debug.mail.maildomain_invitation_txt", + ), + path( + "__debug__/mail/maildomain_invitation_html", + DebugViewMaildomainInvitationHtml.as_view(), + name="debug.mail.maildomain_invitation_html", + ), ] diff --git a/src/backend/debug/views.py b/src/backend/debug/views.py index 3904e7f..26eff8d 100644 --- a/src/backend/debug/views.py +++ b/src/backend/debug/views.py @@ -8,25 +8,49 @@ class DebugBaseView(TemplateView): def get_context_data(self, **kwargs): """Generates sample datas to have a valid debug email""" - context = super().get_context_data(**kwargs) context["title"] = "Development email preview" - return context -class DebugViewHtml(DebugBaseView): - """Debug View for HTML Email Layout""" +# TEAM INVITATION +class DebugViewTeamInvitationHtml(DebugBaseView): + """Debug view for team invitation html email layout""" - template_name = "mail/html/invitation.html" + template_name = "mail/html/team_invitation.html" -class DebugViewTxt(DebugBaseView): - """Debug View for Text Email Layout""" +class DebugViewTeamInvitationTxt(DebugBaseView): + """Debug view for team invitation text email layout""" - template_name = "mail/text/invitation.txt" + template_name = "mail/text/team_invitation.txt" +# MAIL DOMAIN INVITATION +class DebugViewMaildomainInvitationBase(DebugBaseView): + """Debug view for mail domain invitation base email layout""" + + def get_context_data(self, **kwargs): + """Add some fake context data for mail domain invitation email layout""" + context = super().get_context_data(**kwargs) + context["domain"] = "example.com" + context["role"] = "owner" + return context + + +class DebugViewMaildomainInvitationHtml(DebugViewMaildomainInvitationBase): + """Debug view for mail domain invitation html email layout""" + + template_name = "mail/html/maildomain_invitation.html" + + +class DebugViewMaildomainInvitationTxt(DebugViewMaildomainInvitationBase): + """Debug view for mail domain invitation text email layout""" + + template_name = "mail/text/maildomain_invitation.txt" + + +# NEW MAILBOX class DebugViewNewMailboxHtml(DebugBaseView): """Debug view for new mailbox email layout""" diff --git a/src/backend/mailbox_manager/models.py b/src/backend/mailbox_manager/models.py index 8814241..4f1373f 100644 --- a/src/backend/mailbox_manager/models.py +++ b/src/backend/mailbox_manager/models.py @@ -7,6 +7,7 @@ from django.contrib.auth.base_user import AbstractBaseUser from django.core import exceptions, validators from django.db import models from django.utils.text import slugify +from django.utils.translation import gettext from django.utils.translation import gettext_lazy as _ from core.models import BaseInvitation, BaseModel, Organization, User @@ -294,6 +295,9 @@ class MailDomainInvitation(BaseInvitation): default=MailDomainRoleChoices.VIEWER, ) + MAIL_TEMPLATE_HTML = "mail/html/maildomain_invitation.html" + MAIL_TEMPLATE_TXT = "mail/text/maildomain_invitation.txt" + class Meta: db_table = "people_mail_domain_invitation" verbose_name = _("Mail domain invitation") @@ -307,6 +311,18 @@ class MailDomainInvitation(BaseInvitation): def __str__(self): return f"{self.email} invited to {self.domain}" + def _get_mail_subject(self): + """Get the subject of the invitation.""" + return gettext("[La Suite] You have been invited to join La Régie") + + def _get_mail_context(self): + """Get the template variables for the invitation.""" + return { + **super()._get_mail_context(), + "domain": self.domain.name, + "role": self.get_role_display(), + } + def get_abilities(self, user): """Compute and return abilities for a given user.""" can_delete = False diff --git a/src/backend/mailbox_manager/tests/api/invitations/test_api_domain_invitations_create.py b/src/backend/mailbox_manager/tests/api/invitations/test_api_domain_invitations_create.py index fd5db23..6de5188 100644 --- a/src/backend/mailbox_manager/tests/api/invitations/test_api_domain_invitations_create.py +++ b/src/backend/mailbox_manager/tests/api/invitations/test_api_domain_invitations_create.py @@ -3,6 +3,8 @@ Tests for MailDomainInvitations API endpoint in People's app mailbox_manager. Focus on "create" action. """ +from django.core import mail + import pytest from rest_framework import status from rest_framework.test import APIClient @@ -70,12 +72,18 @@ def test_api_domain_invitations__admin_should_create_invites(role): client = APIClient() client.force_login(user) + assert len(mail.outbox) == 0 + response = client.post( f"/api/v1.0/mail-domains/{domain.slug}/invitations/", invitation_values, format="json", ) assert response.status_code == status.HTTP_201_CREATED + assert len(mail.outbox) == 1 + email = mail.outbox[0] + assert email.to == [invitation_values["email"]] + assert email.subject == "[La Suite] You have been invited to join La Régie" def test_api_domain_invitations__viewers_should_not_invite_to_manage_domains(): diff --git a/src/mail/mjml/maildomain_invitation.mjml b/src/mail/mjml/maildomain_invitation.mjml new file mode 100644 index 0000000..b2eb7b3 --- /dev/null +++ b/src/mail/mjml/maildomain_invitation.mjml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + {% trans "Welcome to" %} La Régie + + + {% trans "Hello," %} + {% blocktranslate with role=role domain=domain trimmed %} + You have been invited to join La Régie to be {{ role }} of the domain {{ domain }}. + {% endblocktranslate %} + + {% trans "To do so, please log in La Régie via ProConnect, by following this link:" %} + + arrow + {% trans "Go to La Régie"%} + + + + {% trans "What is La Régie?" %} + + + {% trans "La Régie is the administration center of la Suite, where you can manage users, groups and domains. You will be able to:" %} +
    +
  • {% trans "create work groups,"%}
  • +
  • {% trans "invite new members,"%}
  • +
  • {% trans "manage mail domains,"%}
  • +
  • {% trans "create new mail accounts,"%}
  • +
  • {% trans "etc."%}
  • +
+
+ + {% trans "Welcome aboard!" %} + + + +

{% trans "Regards," %}

+

{% trans "La Suite Team" %}

+
+ + +
+
+
+
+ +
+ diff --git a/src/mail/mjml/invitation.mjml b/src/mail/mjml/team_invitation.mjml similarity index 100% rename from src/mail/mjml/invitation.mjml rename to src/mail/mjml/team_invitation.mjml