From c6fcb276135dc7e87bb0d065a93ff89091ff0207 Mon Sep 17 00:00:00 2001 From: ismail Date: Thu, 30 Oct 2025 19:53:26 +0300 Subject: [PATCH] update the email --- .../__pycache__/settings.cpython-313.pyc | Bin 8192 -> 8380 bytes NorahUniversity/settings.py | 22 +- recruitment/__pycache__/forms.cpython-313.pyc | Bin 52188 -> 62237 bytes .../linkedin_service.cpython-313.pyc | Bin 17304 -> 12178 bytes .../__pycache__/models.cpython-313.pyc | Bin 79728 -> 83316 bytes .../__pycache__/signals.cpython-313.pyc | Bin 5962 -> 5962 bytes recruitment/__pycache__/urls.cpython-313.pyc | Bin 16903 -> 18098 bytes recruitment/__pycache__/utils.cpython-313.pyc | Bin 20398 -> 20398 bytes recruitment/__pycache__/views.cpython-313.pyc | Bin 134549 -> 140665 bytes .../views_frontend.cpython-313.pyc | Bin 36975 -> 45713 bytes recruitment/email_service.py | 210 +++++++- recruitment/forms.py | 169 +++++- recruitment/migrations/0001_initial.py | 2 +- .../__pycache__/0001_initial.cpython-313.pyc | Bin 36251 -> 43839 bytes recruitment/models.py | 65 +-- recruitment/tasks.py | 71 ++- recruitment/urls.py | 7 +- recruitment/views.py | 166 +++++- templates/base.html | 4 +- templates/emails/interview_invitation.html | 139 +++++ templates/includes/email_compose_form.html | 509 ++++++++++++++++++ templates/meetings/meeting_details.html | 110 ++-- .../recruitment/candidate_interview_view.html | 67 ++- test_async_email.py | 105 ++++ test_email_attachments.py | 100 ++++ test_email_attachments_clean.py | 267 +++++++++ test_email_composition.py | 218 ++++++++ test_email_form_js.html | 507 +++++++++++++++++ test_html_email_template.py | 176 ++++++ test_interview_email.html | 139 +++++ test_interview_email.txt | 139 +++++ test_simple_email.py | 239 ++++++++ 32 files changed, 3279 insertions(+), 152 deletions(-) create mode 100644 templates/emails/interview_invitation.html create mode 100644 templates/includes/email_compose_form.html create mode 100644 test_async_email.py create mode 100644 test_email_attachments.py create mode 100644 test_email_attachments_clean.py create mode 100644 test_email_composition.py create mode 100644 test_email_form_js.html create mode 100644 test_html_email_template.py create mode 100644 test_interview_email.html create mode 100644 test_interview_email.txt create mode 100644 test_simple_email.py diff --git a/NorahUniversity/__pycache__/settings.cpython-313.pyc b/NorahUniversity/__pycache__/settings.cpython-313.pyc index 4ae63cf778d53147469d759383cbaa32c8ee5bfe..19cff8c374b90b5ba5dbe57aa353b96304884b90 100644 GIT binary patch delta 830 zcmYjPTTc^F5Z>KFV~Zt7f*}%lQW2r2TkdySU<-woUcMGltF=Id0&Q{1U9k0niuc=t ze}gnJKKSMzFg_8UeD%%5Kj7>Zj5}xM`@WeyJ7;pX;QH#W{A06OC4RJhQ)=@ z2erXW?d%=sq)v2E7uUOw>)r2Vdqq#XqW701>S3Ah{U>|TM}6pbNEiso90x-(Tte^H z4>t{9hz2oCE{u>H8V$ii!|Ws6OT#F6Fh-;B@+rnJPG0tLOwa^;Vvmla3J))SxRbj$3uHiavFtc+hCKTLcza>sn0CC(#g4GOW4V**Lz&n^XZ~-X; z7qO(H!%RUeBh6!ELbA%nENhIl!eiY9@jDW7p}byL<*JZMlSXj%X){~S=t!}xJn~C(wa+1HAE;iUylciCih<@=?ACgse zbBPu|Rqd6_DAu3dP^PV#-|h9q#{!5P9rIuy967R;@=<8<##i^M(QfIn{REPkxLXtF9iFfS>G;}V)sm9JNsfgaTX^AhDTV4~IhDkZ%>nnp=>8$JKs6nd!#eWr$fTkt+$3k)i+UoVEJ55v@t5gNcK4I)iL$j~rj zgnNx5OKFTz2IG8-EOIo)7{>(VFi8`bqDf5C6!MtCED8wnJjYlCalC5(tq*N94j_iS_9@7m(VAL)K-+iVd9x3p(Xx`};< f^w3W(;e)k$%5@HG2qPn!;ctd3+ds&_503u^ruU-t diff --git a/NorahUniversity/settings.py b/NorahUniversity/settings.py index 3eb57de..4e7bb3d 100644 --- a/NorahUniversity/settings.py +++ b/NorahUniversity/settings.py @@ -135,9 +135,9 @@ WSGI_APPLICATION = 'NorahUniversity.wsgi.application' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': 'haikal_db', - 'USER': 'faheed', - 'PASSWORD': 'Faheed@215', + 'NAME': 'norahuniversity', + 'USER': 'norahuniversity', + 'PASSWORD': 'norahuniversity', 'HOST': '127.0.0.1', 'PORT': '5432', } @@ -185,14 +185,26 @@ ACCOUNT_SIGNUP_FIELDS = ['email*', 'password1*', 'password2*'] ACCOUNT_UNIQUE_EMAIL = True ACCOUNT_EMAIL_VERIFICATION = 'none' ACCOUNT_USER_MODEL_USERNAME_FIELD = None -ACCOUNT_EMAIL_VERIFICATION = "mandatory" +ACCOUNT_EMAIL_VERIFICATION = "mandatory" ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = True ACCOUNT_FORMS = {'signup': 'recruitment.forms.StaffSignupForm'} -EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' +EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +EMAIL_HOST = '10.10.1.110' #'smtp.gmail.com' +EMAIL_PORT = 2225 #587 +EMAIL_USE_TLS = False +EMAIL_USE_SSL = False +EMAIL_TIMEOUT = 10 + +DEFAULT_FROM_EMAIL = 'norahuniversity@example.com' + +# Gmail SMTP credentials +# Remove the comment below if you want to use Gmail SMTP server +# EMAIL_HOST_USER = 'your_email@gmail.com' +# EMAIL_HOST_PASSWORD = 'your_password' # Crispy Forms Configuration CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5" diff --git a/recruitment/__pycache__/forms.cpython-313.pyc b/recruitment/__pycache__/forms.cpython-313.pyc index 3730ed60962e16c2cf8250544d5334d51d615237..cbf6857f87fe78c444e141fc556929b95b76132a 100644 GIT binary patch delta 19005 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 NqRGcVzBD-7{{RV?K(PP- delta 6855 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 Q_CMNbJ#BkHAyk(8e^zG2GXMYp diff --git a/recruitment/__pycache__/models.cpython-313.pyc b/recruitment/__pycache__/models.cpython-313.pyc index 173f7d34de869e637424133085ea5f7b647c25cd..4fb5e7920732ff37a37da4b877640451a088613f 100644 GIT binary patch delta 16823 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 delta 13885 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 F003Nd4n+U} delta 50 zcmX@5cS?`%GcPX}0}xmDqgitS(HtsDBa9rRNYTebu=tmRhmWB)lFxb&SW0x@%a+PnM_qL z4)_24{@;0g_uO-M|EKcb|6E@5MPcDF8T%=H%IH7(J}f$~cy{(-yHL8sCqpOII~e19Uv#pmRY z_v?$t6!Oo>&C}luO0PP2{nz(JUdop+?A4R+-+7*AGfMBjh(lpI^`E@xS1kG^ zkA9sOea@oKc=VgR=(jBT6_0+G7yX_^pXZ`oFJ4F8a-WRN>DyN`dHt6WIr@fQ^9aNmWsqurbF%j zhNP!VxBr>8R>n&TZrbm401Bs@ZSE3=07MD2^V?P(nh{+u_+Sol8YBV zAdfG;e`Jfjm&AKythGFyNVDg|v!1+ijj-}eL?c^=n*3-Vuh83ZCtvg1aX(+-+i@pf zQZAnOnM_7jTCW}7XH#IiL6+<&CVy@{Um8-LRD33=cTVpFXkjB1HfGB}=$4cr@}jl6 zEJvRnlc@@J^t&arv;j&RvL|xlBq0D@aO86q2Itvp0N zFqd|6Q#m&oGn>@p0+UM|34jokbe!oqtJo`{RTikSi1rZ>u1FOj@>g>i>*G0ZHEq@G zxwGvZ*3P!o9O0SG1lmf;UfU5Ce9%_I+E01=w58I)j>Z4kUS7`U8Ibc)D)(w1G=JQjy$3?S6l8{KYaMHcta|KynT%P_DWfd3 zW7XSuW&$%ycP+Hc2xZ3XC5@EBM4M*-dKogO!!%1_)bH zA5tgMi`gD(o&fWNIGY3^CApCH|2TCc9YAV5(9_OY=$sW7Zi8?~8bm4|B7f;H7=}@K z(A$1cL_21nV@3?~>5n7zlB!OP+J|C-^mZE5S5ZunwN71n8pRBD((_0~9ZTR?Vh4U) z?o~XM$y7dtG>fLWS97*dvmeZCy?mq)(s`t9*$8d-LAy_!;_D3~UHoyXUP2rrr@A!i zIEr;*>MB)lphyr;m(H0);Z^dA*Y0i7Iw#aQ#o-_bbCOTV-^aU1FF$foXAqo0aq%Vy zwp88Cqh2SDo|5ne ziUejhW&G6W1S8v<{1i_j-A1b4Q_)I0RNBS9>0C{3BfW!^?`s#-u^V6!geB=N(t83q z)mvgnqjISDTWZX>=!GG;z>0kxgjMO13eO}`+^bRdp>UGsUY)^(VhHmLxjlo&eH4Th zX&C7U+33|Muc$)gcfBv~4-ff8uP!}~d@+~J_IoYWnn7z8yI5U3(h|aD?7Dn6f*VJ? z%oi6$x`MPJW1&qRX!3|x`Db|@=_=B$0~fVNz#d^I&)VygXDx)T7`oU!N^1w9c2M-J zgRmjRk**`<_kab;*d^%&!6$7Xy@8Y;)7QXyO`Ky_Oj_DPdXqeK=;m*s=s&`1dm$5{ z%>&TPHe&>YMahjf&0*)(X@Im`(x`(d z=E&$JO*({P9`ia6EYx-tY*)nqzeU1G7m(Tx{Iq)-x~IkYJ0RSZB1jjJ@{eE~I>yCG zKIRhAWu$eP6522b4XkLZAgoDIr0EsJ)q5^lr2 zx}Ip+vO*xtOG$L4u#bv8J+118s(xBE3RR;|s@O~BV{M}C2HI-&V$?7UhGA;(LE7MZ zVqkX&|7^F=cN2Y0nE*9!o?j>lj; d#;&s)@-cp^c@#y`rK7n|<|oG!583~G{{`e`U5Wqz delta 2534 zcmZveTTENY8OMF>F*VtRL?NajzHqlOcQD4rHeig+)m#icEMUMuFqedTLIMfFTB%Z5 zRaLT@hoWkw<)If#?Sr>eDpFri`_M}Jaz6E8)Q42sm#QyqC))O^TtWLEkCVFOJ3b~poOq)yv zQ=ia?vE}OX_p23ptJo_(?@rO%hsPU#_x$6k*6R6&QcqVLwyR&*TT4vio|CJ#wqF|QU%YK(P|ScjI>L0R<0F#N zgFkhgmuE%e@I;pvy1dloRF_w}oYA7rRQM;NsffQP?Y9jEZc-HGt-&sTOWqpF-x?lp zqMB|S|3EC~ch8qtQ9TsZ=WRf`xk;rz?5wis^xZ9kx$xY1VP$0=DD&js*ZF%Y{i4&R zsPx~R_wCYkSGcr7`$dL1o59(fUjP#2B`R(6mkHab-_|8~II zm#jjvs>?X52|-Ori>g3oc%@1|_3K0Z%3me)kN#?*#z2iwx738xgFsDz?4^S?2FmE` zfZ6C1IRQPB1@z2+%64g&o*C+L30;-?k<`3YCh5OqyE>?QMx-7D9isg@Xczjk-~*w* z4Z4N?E$9?l9MZK(Y9ge2wnFx(oXs;uuipJPK338QC5@VQ2*@yhu1I*SL#?p#(#NX1 zp}Jd(%>zmC6QrjKtqfaTuP{18Z)?7mwU0vks5Z3$WRqu+MrcL2)Y4~^-9~9oxYX2d zRB2b(Q6oPZFv^kq*G|^82wjWX+Djm(d=L|c=tbBS8^&N9t)17!EU*B91?}MrATRj@ z(n+M={1WrcgKu72IRWy5Cy{=O8oON<6@yvY+U>~BVK9$*JvU|+*?`CfHyHMmDdRhX z!8~o`DKssisV(ngUKPBmwjhU2BV9(?ki~D zJamhB%dU5j?jmi^$63cLbj)h$tUj|oBi}>AJ{rQ;8P>A`Ju71RTgs4}{;-iBplQ-1 zi(Gqo#N07($F$KjOps-sG|4rXLL9w`vsfBpX>I)&$O)fDI*W8dOU|(50VEH^5Mm?9 zA!dwx4qfx~2R%+p3WEiD)8n!%Vz5O2DuOfytJL1>v^>OMjYfN2mJ9~lbieoB;tmG8 zIA*(E?j4!2FEy@Cs)hr<4_;hMpuD6YC-#g>Kn*g%F2hlY|e;O$_4HK3AIO596iYG9!_VSduN5DOzCD(vt z_!uUPBlYCMtYI7)#x->l$QGYKI)k(+cf?wTpk+v#khvcqokiMvV`Y6Q=u2sIR{1P#fO@@`w*39YHFeF9A&n zZF(2T9v?-TpwIgqrZKZh$NFoqAZvQUdHF>xd*Fo!UM(mJILR~UU&r3$^`&nyEh_7= zfpin8C+A}glh81!eIQqR3+W@I!Rt5+XCRyrFYeBNkG98VHLKsE+vuvkR9WpX)DCNt z`#=u(4)(E&wCuviY(B7wdvOZLG~Yw|6sa$N#QbyMpVOAlfMod*(q~Bh*H%2+#rPQ| zE)R|YBY*z&_^|?6_{Lm@H4j0v*v}at>pYH^<_OX{{nZ?R`T=cB-Y%m^Cy~nMAA|<6 z5@Or#@+8s)q;l@(PBHCaY#7Vp*>4ydH K9sWpsE&31Pv?}BP diff --git a/recruitment/__pycache__/utils.cpython-313.pyc b/recruitment/__pycache__/utils.cpython-313.pyc index 98a2ecadc6cb11daee66c23d21d3c1f202d13cb8..62e34b1e5c44fa8b8dc0f71af3ce04e5943afa28 100644 GIT binary patch delta 24 ecmZ2CpK;xMM&8f7yj%=G;AhR8Ie8=RLVo~TGzRwo delta 24 ecmZ2CpK;xMM&8f7yj%=GaFg+CM&Cx>h5i6!#t1Y3 diff --git a/recruitment/__pycache__/views.cpython-313.pyc b/recruitment/__pycache__/views.cpython-313.pyc index 9ec5eb70378edd87ba9301abca634a054db733b1..4ce6a383fa278c1050294d0cadfbdc48208547f2 100644 GIT binary patch delta 33638 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 b!mloY?@(s4fd!)W6^xmw+?RR`l1=@8Lu+_d delta 28528 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 Kwc!8##{UDtm)`9F diff --git a/recruitment/__pycache__/views_frontend.cpython-313.pyc b/recruitment/__pycache__/views_frontend.cpython-313.pyc index 2fd1d55fb4815c56ff8a32eba074135542ee9122..df9b9a7ea078ec390a40eeb18bc73be5c590706c 100644 GIT binary patch delta 11570 zcmch7X>eQTb?CiVNPq-MfB-@4B)EtK#hv0#iK0Y`B)E!~SCm9b5JW;0Bod%LfU>06 z24$tG95=P(>#0@OjpdGKYIk{~JWgB1-IR%6>b$h+y@Fy;Fl{TX(=?rC0$FMtyLrt! z=VBo!QR%!t4>LUc&hnk_Y~Oe9cYvQ=mt6gkB=qwn*hzvQ0$#5|RavehjPCd~(N63hCl#GhB z+#!q8O043zb4cox5t%sd8X9wslW}ppb4cRcPxgyrdWa$vvx`hH-GpIwlh7p7L)aNB zv&Td=qk-@t2LRujhED*+d*8Q70-a6ipBYo$OP5~;%?btFX{ z6{%xL4Kd>>@_vy#Aqq1I>LkO8)B_@QDnUJ1D<_A+h(l>cOap#64W9vgIt@Pp_)Hpp z6!4Qw=!l6rMW;M>8K@G9IclO9*G$<=WwR_1kz*qL7|`87uTIh3BKh zV;LVH;RCLsr;h#rWR0s!J(+aIM@apMduC5l2!{>@$%TJW)u1ovnfH)=UeCfDQK3){ z(xuGuA}Pj^rtjPm@dN^1zi*1TmzF#vnsEZ90}d%sql99w-@V`o%zC2ANwVyl?R5t| z4w_&v-=?FApm))8!S4f7REgu6InP4S9j$hIU2dOy;e5awaLu`cZr7veqB}Ty(iNEX z6VFeEK-o_YBd7r|O9M!LG%%3D--Cl-4fi))Mq0|fF{|aWGqX9m!X_=DnmN1O{L+Au zmT-9uHtv?aFGtdxP~nqKXK`=0TDkLkb=(i^W|>dMN;!H~2l6@cX>k|hN)rao-CDs( zX0^bOW`NA=vjuV~BWtG<(uJ9jce5yyLWQtR=aX)~ZG9i}> zaxz~YEA^?yQq@kwR81VqMoeR)Sm}fm zx$+#q^Tm8#u@-RO?A4C4G=oHS9p%%)pDs=9B~k7FuW%Ny1y2lT&sO2oLYOvB**cs$ zkjqPyn^X@&s6kgQlLzVF%D1{?-lrQTLh2HaL13ies2 zyOVs@x-(Uta}b+ic!+5jdooNu8#W8OldovhLQttc%|5XHDB%m{5`%eT}H^e1Ys zV7K`yS<9C5fd0gJ4puTTlFULPNZqw^E_5(6cNrd4zAE2#Uv=VS(`IgGtC*&CNz&39 zw(!5H*d58xGtE%3En>yirbVpw(TatFO~uVu2l}@v*wMJ984%>wjjYtO`Yrtj`V;+c zU<(t@v^PFsI?$guy$LF&9BVGrmUMK>{jssxQ*sPE)_gnI9r5G0KK>kr;(@1G8-|Hh zG2$c2B^iO&9Pvrp>{CH4w(qBXEo}1yWM|{U{poCGUd_glh0FJOtE_!-0Y0AU_IB5zBT9WB{jMMr=j`E3|)PwRdZ8=Yzllw%D_DP(O zF2y;N^oONWv{bUD@$FOmu$`=wrP+LDv^KAg_H|7kNpUD7)l>fME=``66HtmB~Zo`7tciJ=O^|_Y(fuPGf=W=-izU74las?znKnCyL9`Z9l zqLQW44muQ-&-#~r!7mi$hib|fYs%-y{kUW%ss`O}(!TSxdnX4E^pPfz`UyM{K{SLGoe#jA zyjkKAXSjnd*L=_u&Gj#NL_fSixQ(DlRuGgfxR6f%4@@Tuq7K4||3HJ=H|IqMU7}Cq zzv6U-`|P|6?lJ-LDqYzjrUVB_~-V-NCCOkBOqDBMoGUN*ST_?T7LlnS>X7(&Cg%-RJ zMrl;mch0>SRpR}Oob`I1ips~(CR7Jz&3hn^K5`jMB6tBJDpV|q>byz$goRIeJf|P0 zp7*#3`7G{_5^WK0Swsy=La>5q%WR2BAZKuvoG3w*WFg2#fXfr&j z%`f+^Mj`TyviJ5^z00@O~D}on0ox;|q#Py>rp* z1kQbT$R4UA_?AsN5c~^DOMU*Q#AAiP>l{V)BX}0UO9=4FK%PN>hf7p7o>mM5uK-bb z&>LLvh#NYpNY*3y1X&qp-3!ZL6}Bs)ia?N@5VID|XOa=#*fpwNzb7#25B8n&g5W>H zjCj)`i`hFi(dQcPnH(S=BlX9qOzEDVC!TqTCb@@1u@@pIa30Qy-4OCaq+;iU{1bp^ zPVX{Q1B5CRZ=igE#B6WCKMNfZ-<+F74FiMy1FrG0$-dFa!Jc8)3r9f16-0xqA8YX)t`uipypCL9{ zLXMrJ4bA!~S|AVlp>m@dHx!|`^Uf@L$oYUL7%fCn+Ac{lNIvdeEdm{aCDc`pqiq19 zmQ)dX7tU|mHLf#Ypf?!uERqTouSD_u)C#WT0@3_bDW=gjPOGFGsYfji1XZZYlB)16 zRwjBBF~e%1_%RQ=${S4djN;3X0u)g$xZ&Z4JB}10p1=7(aADdFqOPq@2JsQM5F|#F zP~&kumli`f&%BGF)JdLL)`YS-;`xHo_(YB7y64Wq>5#;U8D$C*2Z`rg5Gp3gOOaFO zOZ)+55lz6;1tj5#9)A)NYY6G8~~m&KW#rqWY9f zf&%9#v~PzIyr<|5ZP~ ztu?G~TNztd>0TWE>hKGr5mk|(DhjLYD}4_Yl(8sca0muR#LyrZ8X|^f!O$Ewv_=fO z1;g%J*05oWmldqr$|AN}!B!iwwFtJBh^<4gb%bqQyvz)18ADYOL!Dr#3mY0x7*rao z1!Hx@xI-}Rh!{HrV@KEs!umCPW5nJr*xPyLAP>-fC}MXBc30T$=4H0~8B}F^Skr#H zqV2l$701gCp`vZY$!ps0whe|0oVVKsZ)jifUG+uuRf4|ieSNjiHn=j%7dS()EUK(C zQo2_t-MgNnzw&fArz|F=%6jP-B`M4Jafa&RiOUBr`Cd7A_27E0_Db&yr-7}v0ap*) z+>0kKpABc|V@gVHzptY9(k?ozb=}@`^k&&L{ng=!&LQX=Z&kgoYZmq#T^Z)JuDf+Z zVcqcUx}odAYZWhtjtF%_Da)h}e4sd(SNwZ|~vlEU&V~aw(mDWq1w12&}hO(H^PTBUJ2J*O;z#g*BBB zh|0Yfr^>7!XQ`jxc18a}?dyi$HLT|sUXyX#fo&=Qt_isL&sSb)31^ugPReqKQ$IaR zhYM$K?+YEjId|>A@2Vn(8o^NW)~WXm?ZUp}msNb>?A@lZuwndm)7V=(uFbz@6`IB_ z=kSJch?AizQdlPx)`bfpV7hxHJ0c~WLP_VE(F$vpcEOsZ@!YK2wymqwFPr|P`j2Y` zRr{JM=Yd>Wlm$|mc`-_!nGp-gDS2^BM;W)rtN5mYhe|Z;i5Lb1!$8>J#Hv&qUQxZI z;&R_K-k>2|g1T{KaLrs3G4Bw}J8m7~%{zGWSj5ZWQWW(Z!HMs&WL&U%`-4_4V~F3l- z26}djrC_`_^8;-v6HFj%k>mKgr7q*DSRWOS52UzS+-Pnt4m8H)3%L7H8Np%*%`^ z?yU}yI~uV}3YN*R> zlUP^{;arKBUp-)jmI?n=kFPQ z|H<%(m$&ZWt*7|YX9eq1yv($&H}jUph^6(0`=%zW?_3#MGq*&{I|cL3JBQBj=AC@V zOd{rUg85w7d;u*#e2QQ6g%A7C$5y_>DU>?jn-xm-^UUNO^8r4%j6$%gty{2lhiyG@ zjIXgC{-ig|dS7nl&5e9>pJ48LPb-*)-*ey5?&tkWE5k7rrP~(KRtwtdx2D3{=7@He zpxyN@`(A74+edlrE?zsiGJLmVUs&D$PW6qlEAv;a*JanI-pIMFsrhF0${?@qkLm|j z#_lOJFXlX-bH#gI6IPU7KlF!3-Z*lj;eCN&cfBVcgpLuVZKRg}oo>@x>&R;td zR@nK{rkFfY<8Y=qR)*KRC;6#^;qHT>D^K6q)_J?IlRxUhoE28QRVozLz;NAK@@5lX z(Rx!GF5P+aOxOy(LT%RMW!zJkVGG9OFoYB+t-P&1mWhZ04mW<=?wAshTuNy{u{=c7 zQ1ZN`I;KG+pHdd_#XDkJKtgc##IXWo=@UpHA_huX%-dUHMnp`M61GcY%#4U7A!bFy zmRP6=kzz_&!B_Ui?1+?5O4GIOSSgOn5>v_%*_J>mYC?cjQp&<>s+a>f4{Iq)@#`J0 zc3k&|%`NLNcE0L_AcQS#>w42Gr(QaB-4xbWubXVISG`(w{b<;<178HJuV=lQb-gQW zs9%S%=~dJ9k+89G-C)_8ZnR$WhmEyxWSK+t>(=JAk~RpWrew|JSSu{~^bie}tn@!T zN>i%*D;2!C^=4r>8^Yi7`KNw4mEZAsw7~iKr+P|vjQ%{T8~(+^GD@wFKR@uAxr7nl;JDFBj zt?WBhxvnPJd$}#HHtK&DS&vy|-;?AXE0NvJ%|BKl`?$?^%p|>Mqyesm_Ww^>F5c$3 zHs&8QyzmOuBw5Xw^h;X5KRglRUg} zZQ`x|>fjDA^hZGCx(|O}P9$IeXP)LI|3Yy;oi1`L0ZtkaoI&ty5EL&;B!FlT0Zt)j zx#pSOIO(aGwv4BNvMAyHY-T_G2VCZnJpi3YdI7$8+tSqkHj2K8K={a(d{wBTKfyjf8F_ zU~`zFbooY}Nh&25B-O>_H_()?AdqwKF3oA1aER^Vc&WAk%I!YWymzZo!p2)#J#Ddk zG&`-6#N9YkOJCwXK4Yp(TNT%P4irVR=2DJ23gWGU^PHXR$oM*nyu?kDof+|Y+}BBm zd=;pFy80n0Q_$~lk}uWJf5p{*XDZ!?r{Hkc~_Abd66h;7bE`(vVVkNh+CP_bH3+u z<^KxkDtGbuUvj@{ULMn>x8H`LQFZ_t&ffQ-FfWv*w`uFr5$Mkbg0&}uiwjXzI-NK; zm)Qu1=8cvMbPHE&HFQj4A5HwQ5=IJNhNt833mW_~d=pKcq;Y?eS;W2Hq7#3fbGemp zg*F}jW@TR){Df(gRD)7d0|1)Vc|JGv(_P+Kzc1+a`U2!BWS);R^>dzpcitCoYi`JJ zS8W|^BZfxIX9#DAt;z4fC;;EYU^%VCYpDgWsC}zQ)nWrR*}z(ds0F@3aUDhV+((5u zt=Fpsb=|sJbG=JY*WZ`Ynubr3h+Lv+fVTxr{#zD7-Eu!us%d>7l^b#|55&}5gTbKR zCTQXPvR2U6Mzl?Wwh7)bc~vv#GE{Ry`?Hzk`)Kb!a?f^HROM-gaW5K8%AbK9L;!)8 zI=4w0X|A%fv;W`FQv{gW0LJYXU!m4i`SAwGO5d8U9j+p#O1x3z>sE&TL#C0}f3{63 zFML1&AicQWztLRd?x}Ho+Jb>z4}^R{teOW{HRb6AvAJsIMA3NNWT%O7|FF9P?fm)f z?X3^cP6VhdV1-p5F|!lRtUxmh%$G*vc0Hgud!B)NBWIS~WZPcxTO`r8&q3W6zs9!s zcQ>MKWCm8fke+U?E4Qsgtd$82gAPDcogRdJezHi8a^Ko+;KJRyeLqJh5a6l-tklg; zX!H?Hg`lZeajxmWpS$_CYZt=#RVzbl`u0m>ai4yUK82b#`NJ+@w_o%}2^C5{!*w3F zR>;$H7rHAnn=K~4pt)kTnfr%s)6f?<5do?RH2gmq2v@F+$bS)!{8CTVk(o^RL1pU4 zbwt5PiIS0#EJjYU=QA9c(M_)O!k3l_S2SQlRFhT@0r7mn` zb20w3`jCctCwM-KJ5}5UVi}34BERIizh=!+ODGB?sKAxg6JPruH2ax~qG#v`H65m= zKc;pI)b0Y^$0jpY>t1Z8kHsW5x{rR?OIzqd9@;wR9#SxR*de3g9$0t7^pJwlLzSHF0F-a+ iyLI6q1<1qV3{fCK0py`t9;Y<)-a7RkAY&10{Qm;Y1Y6hu delta 5199 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 U2DGWquKQW@T}>t1!>SSf4=l' in message + + if is_html: + # Create HTML email with plain text fallback + plain_message = strip_tags(message) + + # Create email with both HTML and plain text versions + email = EmailMultiAlternatives( + subject=subject, + body=plain_message, + from_email=from_email, + to=clean_recipients, + ) + email.attach_alternative(message, "text/html") + else: + # Plain text email + email = EmailMultiAlternatives( + subject=subject, + body=message, + from_email=from_email, + to=clean_recipients, + ) + + # Add attachments if provided + # if attachments: + # for attachment in attachments: + # if hasattr(attachment, 'read'): + # # File-like object + # filename = getattr(attachment, 'name', 'attachment') + # content = attachment.read() + # content_type = getattr(attachment, 'content_type', 'application/octet-stream') + # email.attach(filename, content, content_type) + # elif isinstance(attachment, tuple) and len(attachment) == 3: + # # (filename, content, content_type) tuple + # filename, content, content_type = attachment + # email.attach(filename, content, content_type) + + # Send email + email.send(fail_silently=False) + + logger.info(f"Bulk email sent successfully to {len(clean_recipients)} recipients") + return { + 'success': True, + 'recipients_count': len(clean_recipients), + 'message': f'Email sent successfully to {len(clean_recipients)} recipient(s)' + } + + except Exception as e: + error_msg = f"Failed to send bulk email: {str(e)}" + logger.error(error_msg, exc_info=True) + return {'success': False, 'error': error_msg} diff --git a/recruitment/forms.py b/recruitment/forms.py index 590a0ea..0501c2b 100644 --- a/recruitment/forms.py +++ b/recruitment/forms.py @@ -642,7 +642,7 @@ class LinkedPostContentForm(forms.ModelForm): class Meta: model = JobPosting fields = ['linkedin_post_formated_data'] - + class FormTemplateIsActiveForm(forms.ModelForm): class Meta: model = FormTemplate @@ -1188,14 +1188,175 @@ class ParticipantsSelectForm(forms.ModelForm): widget=forms.CheckboxSelectMultiple, required=False, label=_("Select Participants")) - + users=forms.ModelMultipleChoiceField( queryset=User.objects.all(), widget=forms.CheckboxSelectMultiple, required=False, label=_("Select Users")) - + class Meta: model = JobPosting fields = ['participants','users'] # No direct fields from Participants model - \ No newline at end of file + + +class CandidateEmailForm(forms.Form): + """Form for composing emails to participants about a candidate""" + + subject = forms.CharField( + max_length=200, + widget=forms.TextInput(attrs={ + 'class': 'form-control', + 'placeholder': 'Enter email subject', + 'required': True + }), + label=_('Subject'), + required=True + ) + + message = forms.CharField( + widget=forms.Textarea(attrs={ + 'class': 'form-control', + 'rows': 8, + 'placeholder': 'Enter your message here...', + 'required': True + }), + label=_('Message'), + required=True + ) + + recipients = forms.MultipleChoiceField( + widget=forms.CheckboxSelectMultiple(attrs={ + 'class': 'form-check' + }), + label=_('Recipients'), + required=True + ) + + include_candidate_info = forms.BooleanField( + widget=forms.CheckboxInput(attrs={ + 'class': 'form-check-input' + }), + label=_('Include candidate information'), + initial=True, + required=False + ) + + include_meeting_details = forms.BooleanField( + widget=forms.CheckboxInput(attrs={ + 'class': 'form-check-input' + }), + label=_('Include meeting details'), + initial=True, + required=False + ) + + + def __init__(self, job, candidate, *args, **kwargs): + super().__init__(*args, **kwargs) + self.job = job + self.candidate = candidate + + # Get all participants and users for this job + recipient_choices = [] + + # Add job participants + for participant in job.participants.all(): + recipient_choices.append( + (f'participant_{participant.id}', f'{participant.name} - {participant.designation} (Participant)') + ) + + # Add job users + for user in job.users.all(): + recipient_choices.append( + (f'user_{user.id}', f'{user.get_full_name() or user.username} - {user.email} (User)') + ) + + self.fields['recipients'].choices = recipient_choices + self.fields['recipients'].initial = [choice[0] for choice in recipient_choices] # Select all by default + + # Set initial subject + self.fields['subject'].initial = f'Interview Update: {candidate.name} - {job.title}' + + # Set initial message with candidate and meeting info + initial_message = self._get_initial_message() + if initial_message: + self.fields['message'].initial = initial_message + + def _get_initial_message(self): + """Generate initial message with candidate and meeting information""" + message_parts = [] + + # Add candidate information + if self.candidate: + message_parts.append(f"Candidate Information:") + message_parts.append(f"Name: {self.candidate.name}") + message_parts.append(f"Email: {self.candidate.email}") + message_parts.append(f"Phone: {self.candidate.phone}") + + # Add latest meeting information if available + latest_meeting = self.candidate.get_latest_meeting + if latest_meeting: + message_parts.append(f"\nMeeting Information:") + message_parts.append(f"Topic: {latest_meeting.topic}") + message_parts.append(f"Date & Time: {latest_meeting.start_time.strftime('%B %d, %Y at %I:%M %p')}") + message_parts.append(f"Duration: {latest_meeting.duration} minutes") + if latest_meeting.join_url: + message_parts.append(f"Join URL: {latest_meeting.join_url}") + + return '\n'.join(message_parts) + + def clean_recipients(self): + """Ensure at least one recipient is selected""" + recipients = self.cleaned_data.get('recipients') + if not recipients: + raise forms.ValidationError(_('Please select at least one recipient.')) + return recipients + + def get_email_addresses(self): + """Extract email addresses from selected recipients""" + email_addresses = [] + recipients = self.cleaned_data.get('recipients', []) + for recipient in recipients: + if recipient.startswith('participant_'): + participant_id = recipient.split('_')[1] + try: + participant = Participants.objects.get(id=participant_id) + email_addresses.append(participant.email) + except Participants.DoesNotExist: + continue + elif recipient.startswith('user_'): + user_id = recipient.split('_')[1] + try: + user = User.objects.get(id=user_id) + email_addresses.append(user.email) + except User.DoesNotExist: + continue + + return list(set(email_addresses)) # Remove duplicates + + def get_formatted_message(self): + """Get the formatted message with optional additional information""" + message = self.cleaned_data.get('message', '') + + # Add candidate information if requested + if self.cleaned_data.get('include_candidate_info') and self.candidate: + candidate_info = f"\n\n--- Candidate Information ---\n" + candidate_info += f"Name: {self.candidate.name}\n" + candidate_info += f"Email: {self.candidate.email}\n" + candidate_info += f"Phone: {self.candidate.phone}\n" + message += candidate_info + + # Add meeting details if requested + if self.cleaned_data.get('include_meeting_details') and self.candidate: + latest_meeting = self.candidate.get_latest_meeting + if latest_meeting: + meeting_info = f"\n\n--- Meeting Details ---\n" + meeting_info += f"Topic: {latest_meeting.topic}\n" + meeting_info += f"Date & Time: {latest_meeting.start_time.strftime('%B %d, %Y at %I:%M %p')}\n" + meeting_info += f"Duration: {latest_meeting.duration} minutes\n" + if latest_meeting.join_url: + meeting_info += f"Join URL: {latest_meeting.join_url}\n" + message += meeting_info + + return message diff --git a/recruitment/migrations/0001_initial.py b/recruitment/migrations/0001_initial.py index 1e9fde3..306ceb7 100644 --- a/recruitment/migrations/0001_initial.py +++ b/recruitment/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.2.7 on 2025-10-29 18:04 +# Generated by Django 5.2.6 on 2025-10-30 10:22 import django.core.validators import django.db.models.deletion diff --git a/recruitment/migrations/__pycache__/0001_initial.cpython-313.pyc b/recruitment/migrations/__pycache__/0001_initial.cpython-313.pyc index 8d49e501f96f38e198262db6b7e7b656884ee136..b86dad7c1efe753588061d054a57b36d6d5db2ed 100644 GIT binary patch delta 12536 zcmb7K3tU`RnV)-y*Dy@x!JA>=!te-58XyTtNKy&`LI{M{0YZReGB5)Sj~OyE5STos zR;#v6Yn!7sZq=gIHLZ_Qaou!vTddYbU3F$wCCpZB?N&{@+DYqc)z$sJbM8zgw%xk@ z_1=5F_jkVYKi@e+`_Mz;(?1e7yrI#gD&QaIKBZ&y%MWb$uDSwA_~(tumM4DxZ~}d; z^g;S@(Wn+lJrPL**zywh?mT)Ul6&d$rd5&Lht*TplMl!%azFY{-UePCAQxzw%A8EuN_~(@rd-vB zNGhw`hndwBc~G{x2s6l4eMFZ216BuC{UP#EX8SSpsX?C~msj~=%uKZ;%Rj-WPs-FI zjQW&JeVWdu<)wk?Ka$U|LSI5>=^}X)3Mi7t$Y-%Em3kQ@pX0OoJj?G3#7Od429Hyn zF;7R9q3}qrZ%Sg@2|}npwC^Ul7fzCyB(&{{@mTslGzK%Jlw~ z**z7rdm2llUL{|XwVz=V__|DegGrwy-<0X+E^M0Akt^g|65?~`3D3k01}6_EV|sZ{9{Nr(o@vNn)^MHC~FV zblGG|US}S{Ec5?}W&S*UN@r64m{gLVFv$KCd=AkcXF+*iK))&6FL@DiHjtl@m*kvP zipC-NiKOZ_;RhHkpU%?<)zU3`5 z8m8xr+3L=iei!O%yKkC$4^CDG&I#{dEcIU4j(LdfzF7AC%=QSJoN{g;9e}1)E*!<3 zOuu7F69%z~v28RITlisSckCv+turc(t&$HWnKcXd>8b+`S3jr&lz~m;)Y{^&H?3T zXF$1dJ9Oc%3-3a>sP7=`AP4EY8U3CZeJ8esG!VR3KEG3Ffs{)#r7gny*yy#2B=!4a zUF5D9@9r4y9;jvxF6(*j0!H^@*|peb?u+%4jckftJCn5^0RH{(Jb+~4i-*$*A)|@@;A;E>HXrGU;kb4%L*@O)ej^e|?bj#)0j^NCnT{Nx24gXtqgFKd44f-VQU z^rzwZM|hYAB3}f7{)~LYu#J^{iS;AAqdW$($8eVL{cIHdpNo~`^AHFV`vODZ$WaKR6{t$)mtar<&p*Kf6O5J1^krbg%^a=+THyRMJeOrSJc->m1sMMV z{eA@deePG@W`o;sgR8z8U5;qwlm8Wiz?yu#v|M;9>h5XgZdNkpuKr){lE20ly9HaY z8gKA>{or5Ih&%M8Xx^V#(iP zAzoze>NO<$CD36Yt4xN`x8eB?JnVQ9{*5{PE;h!@??Ge4M*V$w0_X$2aN~kR>tPfk zx5&JIXFP1RKZx;uh*wq`sYq1+D7Hb?V!W#{-a50z{Thzh{s%6*>UsI{fLnQs|H-Dy4q!b_>Scb{ zg3-@o=Si0?19$Z=cs?-tB{p?rU5l|^fxDSW`zrAM3!Y!Gg5%{hk2Yq@_oyAs=2+TY42*6;X&M@N16h z$_lWB{T`1M_&x{~(Eb4i_wy?&jIgIL7T{N2z5j+ZPip@N!awnwE{y&hg`VbrfclGk z<5fqI_g4gcLW@Wga5zEB6Nw-%j|kVt7jklqB2fYtE|6p^^6$`N_6Y@R5Z`QO2R7Bvbv1 z*sQa8pd2|+Zd{-|5EY69uXh*+4=j$wWS~s&6fi7ej6#NmI}<%vTM4f)*@-YJg0?7< zVtCA~*NLPAiwqMg1zs6E<@lo?N>zZ>+bFkdkyJpt##wBFXEVg*4PON0Et}wSEs|U0 z-2%&m_0$vquTt*etgEx@hTPRbRwd(tl)|4afX1cW9-ELFs2%XskRMeF&<-b{yJo`A zD5(;cdM7;a8!nDt!T7u5_*G(Nrk!zXIkysFv}bDqy>C+?6bOD2ZTcE~_hBb7faq3M znmPt$k=zEmFwekP^&o7J+52Gy^de~lR+9{Sku(DnV2aEGGQLw_+yc+RxEz~VHm$&o z%e_b>`x*Zb=fm$Lk+f}9lCoN5moS{zGl?@#7D+qv1hdM$%JdI&eRy}&!c8Skvr~?l zo%=4P+4Xm5zME-wzk?=54>HZ3x75r|{7@`QEz=|KsK?i+_igkZjQM+x`RjW}Js!9J zE%mUDN21j+u8>Qt+5>-wE|qnUzO!!br&y+g@1Tjb89SAlvi*t8GgilRh3GB@9k&)<*V0fst!u*Nv`ZaxGb46)SZ%X= z9OF)_*Wq$rvw=LUZo0tWVF4s*vz?tGkDAHGWP z6`d(BZdmOFLrW|RWlM9fdl>cb8>jC7DY3TJudW@lY) zug4Ody9EpAt2;6QGqt-V?}Wo6dDwDGQC;viYIn@P#R84FT{8#=Ulx)5N}bW=!uo}i z5g@dtv4C0{cM3N8;l{h^&ZcK_5N*7Y452%aM3~aN=B`BdZXBI#epKjNF&_A}sJ;iq z=kawf&1mfdKa;IP@cw4&@6s!jZssh8boV0t!J%gd5&`{}&;(zIjOGRFjQdees9K#~ zyL;YYKjnUma}qnp#_VqQXJzW3!)>>@KL=Dek$A1+_KHNl`ZoGf+cv}FOwIi<`0&@` zw7lI!|In06kG0=Y@kQ<>=>Tj(aI*rWPmS><@a3KJfHRIKy3&5v-pgD&rN@rT3;Iu@ zei}Y5vwc8t1L<>0I!PV2P$Yn+kPFm88_F1nuqk}3H#5EfnXEg$n~O=gPW zRQl@SlAH>8r?3T$U$%W6KTY{Ix>maTsJU}M_#r*h`39`vY*%H9=r&=PV){hap5jL# zxrWBx*8XO9i=0bidnajb3MVyAyF7N=qg2zqRr4~+5~7Q8u-hfPNH2Fkmv5YQIH&B; zO)Rr6*ptvfW}r~4bXIzYPg*VJt7c8+R@9|Y1wk|kk z=4Ng*evbs34S#O3LDUD4Ux zNYAH{rXs1cEFa?2363<0^+(OE39|99perFo+Ya8Gk3}?Daw*Y z?68sS5_9B%W6R^y$CRQz!)mK-2KJrP1!tPC#2 zujI8FjV_QoPk0oX@_POPMdQ&;A&#=x~A;TYxUs8m)6HvQZKRqExdn%#9fFlwh^>e=E5=y z67eF1?6oz3er!F>U{AzT)? z0}0zM;Dc%SQk(ez%{0?i=)+tKAgE~v5@3$A1NfzJfn^k~cwS#x!>FJ2(?%r2sW*TE z;Nr8vIKIO8j>cgDkcrbyZHP4;pFze5k11hEeR6k_^I$wrxB$KGms`6?y4QkI)N>Vy9`~Fql;t* z?7#&()gSkABz~0MbNoJ9YT1(Lz8wHW2QAy-uh#cj{_IMBt4XqaqbYC&i)BY`wY7!? z44dMrWWg=vfMal1?QZLC%;)AA$UEIqv&*)9WCzZmQ=UQX_L17^T6z8w;#vzYs0Ay7 zHipe{c7Y71LLfYO0o8EUpTx;#;_JDUM@}dOp?2jn)*lLbGGm>d#s)ENcOP)rr)|_X zx(QD3Pmey3k=`&3MUz zIH9I5*?U2s?WJtwwAX!l(%`=b0s^N z*B#LH$jnWlyiLm)tHr239n6~v=$u#e1xrb5QdLN*TJ~O1273Afc6U(n1a#hrUX`&S zlBLiaFE&S%V&;bHxms0f#451h^`b(RzLruDTKU5Gt)l;`URo;qOywslFDFD4idNx( z2%p1ZH-1itF7diTVV*@oe^R_DX5c`7U|=lJJRUfC3dBv~G-@r1r}1-0c|-}8MFUE- zJgU6Oa@85==Z5nUze3R{j-!cJoX1bIvWHm`X4wmtMN2!^%-cie?UzeH-X=7%0AdGz zj)^mvVTlt7y$dp|xU_R^b6se2-Rc~$jtWOnG9lKZ(=83m>3(ITA`>dKRZ&!7yjos$ z)nvYS@Op9r6bk;tof>I?)q({)v!a_^6H?A{%DM8|RHmqMDVb~}VMXJt6Ea5=72-I;KH%*KYcMP8V`lwe zmVa?CTV30O=(*59ISagWsplA|Z>!-wZUi@7l z^RCObD;dGz>7W_G_c!@ig4Vgfp?R=rfEiraVP&YW za@n?;5$rt?EVKr6BkTIYrL57lqUuml_2q;})@taL;b^+@S1YzPg#O9%ZD~1i-9Q6m3~A-~M`{5+KmmzAW!;RZT2w+0t>C zp)eHR*qc|j2hE)UT~{O%WmyVCNffeAx&nj8LZ!z8I!h!QgpnMDp)ep-uSvUu((W~> zB`CE7`bGlqmJptiT=bAfTjz_Dj5y4vC+G8$OgJo{56l-O72;5$m*|9F{2z=A{E`B|AbTJ1*M;T|J=^643QV%0U>} zNN+!tmsEknO?2th_N2{dvW2dn>PflfDnGU*}u%f(&(Ha2btO$Mi`P#zpcfbxSvD+f92?9-xG{Jlak4J{62 z@`orLti??-gp8WVl^@ry^%$%OJ8SQ`|@er8^u5b0#* zU9`+MzoVOt`vpbO*7fq5tENpCJ9&FQDpX^C=clkOC2lX3(4ha0m7df6g36x4x^{<( zK5^!Ns#C?N0o8@Ghcl0IVnh{ZS%#K=c1YEQ%yq%mGmu|9G!EzyC05q?MxgVRBR-o# z6-`&VK|TcC8$R7|^ucG-1XFW>8fzsxL&ZC>U5^Ee#{;^FIBu|E3iMA4htRv3^+tU= zoO*uN@Tx-v)t5`YH54p38qf`1)#qN^xn|rPGH!;BRx^Z=>~LN}+wqBK@YALwxCZ&X ztcZQk$x4>S*2-!_WwooN!G1@uY%-vmlDT_AWqY7!cVnAB7fs)WPRs3L1u*qvkbm5z zB-k<}P8dMJINUKX2l7 z{9Z3n6zyIwzb$TM%X461NBQ#frqcei_pAC+*~-~c>1$`Fw%v3CVfUq=gq!N^Z&-Bj zTvNI_3Bo0+z`32fTS#4b;+$GgEpl=|O`r8YFRao}-rfTLW&f4ipUyn0W^oUt#eu|( zAffeltg715nADj@pEy@RFO2QlARn^qhSM8dIrVP0km=%D9hx{Fg>bJhuH@eNh@k4! zFeeL|m1p1ECuA;ia&SYOwi&d`XxixmemGm@qqXK+J%NGY;M8KM$QRI^Ue^~#`(g05 zq2RSi*iWlAQ)CmaizPSufv*0P%NT%`bkq{U6$&C{lZ~%*9*N0+)W8{=+5pR>ONt!O#x0B_Lm`!Z<^8X!TC{8>C$;qP zyGm43oN{aF^LLq59!~kRH05ry>NKbJ>*x-k8gkdB@Js*O`UNM+EayR|C9IfFWS z`EGOO5T{0TEDvKS#kihbOzZE?_K$MOWV~d{RYT5$TP|$*#KLk;plnaD!5T7*z-0tx zG{x23Z>c_aX(CXz3jh%^9OvpDuI_tFbw4PN1nZ863>L0^nrrXZ$7LDKW$ENgQns!yTQ_YDvucP_BYHZ1PuZSP zPEE##-7J?NSiUP*+Zrf46zo13GPt?xDQ@7_)93CfQ+YV$)3e&Ao;RpYbIyJPEj@2e zZ8Tt}cOG(Ir9J1(!qasAd@Xc}MZz+ToX>~<$47H-Ro)}`Q}!yp*5MUS l**D{|%}v|u+&`m7?!6`Zuu4d}KXpx464aIaR)G{#{$CmiwSoWu delta 7453 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 diff --git a/recruitment/models.py b/recruitment/models.py index 5e80ec2..1c7676e 100644 --- a/recruitment/models.py +++ b/recruitment/models.py @@ -38,7 +38,7 @@ class Profile(models.Model): class JobPosting(Base): # Basic Job Information - + JOB_TYPES = [ ("FULL_TIME", "Full-time"), ("PART_TIME", "Part-time"), @@ -61,12 +61,12 @@ class JobPosting(Base): help_text=_("Internal staff involved in the recruitment process for this job"), ) - participants=models.ManyToManyField('Participants', + participants=models.ManyToManyField('Participants', blank=True,related_name="jobs_participating", verbose_name=_("External Participant"), help_text=_("External participants involved in the recruitment process for this job"), ) - + # Core Fields title = models.CharField(max_length=200) department = models.CharField(max_length=100, blank=True) @@ -362,21 +362,21 @@ class JobPosting(Base): @property def offer_candidates_count(self): return self.all_candidates.filter(stage="Offer").count() or 0 - + @property def hired_candidates_count(self): return self.all_candidates.filter(stage="Hired").count() or 0 - + @property def vacancy_fill_rate(self): total_positions = self.open_positions - + no_of_positions_filled = self.candidates.filter(stage__in=['HIRED']).count() if total_positions > 0: vacancy_fill_rate = no_of_positions_filled / total_positions else: - vacancy_fill_rate = 0.0 + vacancy_fill_rate = 0.0 return vacancy_fill_rate @@ -678,12 +678,12 @@ class Candidate(Base): ).exists() return future_meetings or today_future_meetings - + # @property # def time_to_hire(self): # time_to_hire=self.hired_date-self.created_at # return time_to_hire - + class TrainingMaterial(Base): @@ -751,43 +751,19 @@ class ZoomMeeting(Base): # Timestamps def __str__(self): - return self.topic - + return self.topic\ @property def get_job(self): - try: - job=self.interview.job.first() - return job - except: - return None + return self.interview.job @property def get_candidate(self): - try: - candidate=self.interview.candidate.first() - return candidate - except: - return None - + return self.interview.candidate @property - def get_external_participants(self): - try: - interview=self.interview.first() - if interview: - return interview.job.participants.all() - return None - except: - return None + def get_participants(self): + return self.interview.job.participants.all() @property - def get_users_participants(self): - try: - interview=self.interview.first() - if interview: - return interview.job.users.all() - return None - except: - return None - - + def get_users(self): + return self.interview.job.users.all() class MeetingComment(Base): """ @@ -1629,8 +1605,8 @@ class InterviewSchedule(Base): models.Index(fields=['end_date']), models.Index(fields=['created_by']), ] - - + + class ScheduledInterview(Base): """Stores individual scheduled interviews""" @@ -1641,8 +1617,8 @@ class ScheduledInterview(Base): related_name="scheduled_interviews", db_index=True ) - - + + job = models.ForeignKey( "JobPosting", on_delete=models.CASCADE, related_name="scheduled_interviews", db_index=True ) @@ -1766,4 +1742,3 @@ class Participants(Base): def __str__(self): return f"{self.name} - {self.email}" - \ No newline at end of file diff --git a/recruitment/tasks.py b/recruitment/tasks.py index c7ec331..06cb795 100644 --- a/recruitment/tasks.py +++ b/recruitment/tasks.py @@ -147,7 +147,7 @@ def format_job_description(pk): 2. **Format the Qualifications:** Organize and format the raw QUALIFICATIONS data into clear, readable sections using `

` headings and `
    `/`
  • ` bullet points. Encapsulate the entire formatted block within a single `
    `. 3. **Format the Benefits:** Organize and format the raw Requirements data into clear, readable sections using `

    ` headings and `
      `/`
    • ` bullet points. Encapsulate the entire formatted block within a single `
      `. 4. **Application Instructions:** Organize and format the raw Requirements data into clear, readable sections using `

      ` headings and `
        `/`
      • ` bullet points. Encapsulate the entire formatted block within a single `
        `. - + **TASK 2: LinkedIn Post Creation** 1. **Write the Post:** Create an engaging, professional, and concise LinkedIn post (maximum 1300 characters) summarizing the opportunity. @@ -744,3 +744,72 @@ def sync_candidate_to_source_task(candidate_id, source_id): error_msg = f"Unexpected error during sync: {str(e)}" logger.error(error_msg, exc_info=True) return {"success": False, "error": error_msg} + + +def send_bulk_email_task(subject, message, recipient_list, request=None, attachments=None): + """ + Django-Q background task to send bulk email to multiple recipients. + + Args: + subject: Email subject + message: Email message (can be HTML) + recipient_list: List of email addresses + request: Django request object (optional) + attachments: List of file attachment data (optional) + + Returns: + dict: Result with success status and error message if failed + """ + from .email_service import send_bulk_email + import os + + logger.info(f"Starting bulk email task for {len(recipient_list)} recipients") + + try: + # Process attachments - convert file data back to file objects if needed + # processed_attachments = [] + # if attachments: + # for attachment in attachments: + # if isinstance(attachment, dict) and 'file_path' in attachment: + # # This is a serialized file from background task + # file_path = attachment['file_path'] + # filename = attachment.get('filename', os.path.basename(file_path)) + # content_type = attachment.get('content_type', 'application/octet-stream') + + # try: + # with open(file_path, 'rb') as f: + # content = f.read() + # processed_attachments.append((filename, content, content_type)) + + # # Clean up temporary file + # try: + # os.unlink(file_path) + # except OSError: + # pass # File might already be deleted + + # except FileNotFoundError: + # logger.warning(f"Attachment file not found: {file_path}") + # continue + # else: + # # Direct attachment (file object or tuple) + # processed_attachments.append(attachment) + + # Call the existing send_bulk_email function synchronously within the task + result = send_bulk_email( + subject=subject, + message=message, + recipient_list=recipient_list, + request=request, + ) + + if result['success']: + logger.info(f"Bulk email task completed successfully for {result.get('recipients_count', len(recipient_list))} recipients") + else: + logger.error(f"Bulk email task failed: {result.get('error', 'Unknown error')}") + + return result + + except Exception as e: + error_msg = f"Critical error in bulk email task: {str(e)}" + logger.error(error_msg, exc_info=True) + return {'success': False, 'error': error_msg} diff --git a/recruitment/urls.py b/recruitment/urls.py index e65036e..d15e4e4 100644 --- a/recruitment/urls.py +++ b/recruitment/urls.py @@ -65,7 +65,7 @@ urlpatterns = [ path('forms/builder//', views.form_builder, name='form_builder'), path('forms/', views.form_templates_list, name='form_templates_list'), path('forms/create-template/', views.create_form_template, name='create_form_template'), - + path('jobs//edit_linkedin_post_content/',views.edit_linkedin_post_content,name='edit_linkedin_post_content'), path('jobs//candidate_screening_view/', views.candidate_screening_view, name='candidate_screening_view'), path('jobs//candidate_exam_view/', views.candidate_exam_view, name='candidate_exam_view'), @@ -225,5 +225,8 @@ urlpatterns = [ path('participants/create/', views_frontend.ParticipantsCreateView.as_view(), name='participants_create'), path('participants//', views_frontend.ParticipantsDetailView.as_view(), name='participants_detail'), path('participants//update/', views_frontend.ParticipantsUpdateView.as_view(), name='participants_update'), - path('participants//delete/', views_frontend.ParticipantsDeleteView.as_view(), name='participants_delete'), + path('participants//delete/', views_frontend.ParticipantsDeleteView.as_view(), name='participants_delete'), + + # Email composition URLs + path('jobs//candidates//compose-email/', views.compose_candidate_email, name='compose_candidate_email'), ] diff --git a/recruitment/views.py b/recruitment/views.py index 7775494..fdae077 100644 --- a/recruitment/views.py +++ b/recruitment/views.py @@ -41,7 +41,8 @@ from .forms import ( AgencyAccessLinkForm, AgencyJobAssignmentForm, LinkedPostContentForm, - ParticipantsSelectForm + ParticipantsSelectForm, + CandidateEmailForm ) from easyaudit.models import CRUDEvent, LoginEvent, RequestEvent from rest_framework import viewsets @@ -415,12 +416,12 @@ def job_detail(request, slug): ) ) total_candidates=applicants.count() - avg_match_score_result = candidates_with_score.aggregate(avg_score=Avg('annotated_match_score'))['avg_score'] - avg_match_score = round(avg_match_score_result or 0, 1) + avg_match_score_result = candidates_with_score.aggregate(avg_score=Avg('annotated_match_score'))['avg_score'] + avg_match_score = round(avg_match_score_result or 0, 1) high_potential_count = candidates_with_score.filter(annotated_match_score__gte=HIGH_POTENTIAL_THRESHOLD).count() high_potential_ratio = round( (high_potential_count / total_candidates) * 100, 1 ) if total_candidates > 0 else 0 - + # --- 3. Time Metrics (Duration Aggregation) --- # Metric: Average Time from Applied to Interview (T2I) @@ -539,14 +540,14 @@ def edit_linkedin_post_content(request,slug): else: messages.error(request,"Error update the Linkedin Post content") return redirect('job_detail',job.slug) - + else: linkedin_content_form=LinkedPostContentForm() return redirect('job_detail',job.slug) - - + + def kaauh_career(request): @@ -1434,41 +1435,41 @@ def candidate_update_status(request, slug): @login_required def candidate_interview_view(request,slug): job = get_object_or_404(JobPosting,slug=slug) - + if request.method == "POST": form = ParticipantsSelectForm(request.POST, instance=job) print(form.errors) - + if form.is_valid(): - + # Save the main instance (JobPosting) job_instance = form.save(commit=False) job_instance.save() - + # MANUALLY set the M2M relationships based on submitted data job_instance.participants.set(form.cleaned_data['participants']) job_instance.users.set(form.cleaned_data['users']) - + messages.success(request, "Interview participants updated successfully.") return redirect("candidate_interview_view", slug=job.slug) - + else: - # 🛑 FIX: Explicitly pass the initial data for M2M fields initial_data = { 'participants': job.participants.all(), 'users': job.users.all(), } form = ParticipantsSelectForm(instance=job, initial=initial_data) - + else: form = ParticipantsSelectForm(instance=job) - - + + context = { "job":job, "candidates":job.interview_candidates, 'current_stage':'Interview', - 'form':form + 'form':form, + 'participants_count': job.participants.count() + job.users.count(), } return render(request,"recruitment/candidate_interview_view.html",context) @@ -3557,3 +3558,132 @@ def api_candidate_detail(request, candidate_id): except Exception as e: return JsonResponse({'success': False, 'error': str(e)}) + + +@login_required +def compose_candidate_email(request, job_slug, candidate_slug): + """Compose email to participants about a candidate""" + from .email_service import send_bulk_email + + job = get_object_or_404(JobPosting, slug=job_slug) + candidate = get_object_or_404(Candidate, slug=candidate_slug, job=job) + if request.method == 'POST': + form = CandidateEmailForm(job, candidate, request.POST) + if form.is_valid(): + # Get email addresses + email_addresses = form.get_email_addresses() + if not email_addresses: + messages.error(request, 'No valid email addresses found for selected recipients.') + return render(request, 'includes/email_compose_form.html', { + 'form': form, + 'job': job, + 'candidate': candidate + }) + + # Check if this is an interview invitation + subject = form.cleaned_data.get('subject', '').lower() + is_interview_invitation = 'interview' in subject or 'meeting' in subject + + if is_interview_invitation: + # Use HTML template for interview invitations + meeting_details = None + if form.cleaned_data.get('include_meeting_details'): + # Try to get meeting details from candidate + meeting_details = { + 'topic': f'Interview for {job.title}', + 'date_time': getattr(candidate, 'interview_date', 'To be scheduled'), + 'duration': '60 minutes', + 'join_url': getattr(candidate, 'meeting_url', ''), + } + + from .email_service import send_interview_invitation_email + email_result = send_interview_invitation_email( + candidate=candidate, + job=job, + meeting_details=meeting_details, + recipient_list=email_addresses + ) + else: + # Get formatted message for regular emails + message = form.get_formatted_message() + subject = form.cleaned_data.get('subject') + + # Send emails using email service (no attachments, synchronous to avoid pickle issues) + email_result = send_bulk_email( + subject=subject, + message=message, + recipient_list=email_addresses, + request=request, + async_task_=False # Changed to False to avoid pickle issues + ) + + if email_result['success']: + messages.success(request, f'Email sent successfully to {len(email_addresses)} recipient(s).') + + # For HTMX requests, return success response + if 'HX-Request' in request.headers: + return JsonResponse({ + 'success': True, + 'message': f'Email sent successfully to {len(email_addresses)} recipient(s).' + }) + + return redirect('candidate_interview_view', slug=job.slug) + else: + messages.error(request, f'Failed to send email: {email_result.get("message", "Unknown error")}') + + # For HTMX requests, return error response + if 'HX-Request' in request.headers: + return JsonResponse({ + 'success': False, + 'error': email_result.get("message", "Failed to send email") + }) + + return render(request, 'includes/email_compose_form.html', { + 'form': form, + 'job': job, + 'candidate': candidate + }) + + # except Exception as e: + # logger.error(f"Error sending candidate email: {e}") + # messages.error(request, f'An error occurred while sending the email: {str(e)}') + + # # For HTMX requests, return error response + # if 'HX-Request' in request.headers: + # return JsonResponse({ + # 'success': False, + # 'error': f'An error occurred while sending the email: {str(e)}' + # }) + + # return render(request, 'includes/email_compose_form.html', { + # 'form': form, + # 'job': job, + # 'candidate': candidate + # }) + else: + # Form validation errors + print(form.errors) + messages.error(request, 'Please correct the errors below.') + + # For HTMX requests, return error response + if 'HX-Request' in request.headers: + return JsonResponse({ + 'success': False, + 'error': 'Please correct the form errors and try again.' + }) + + return render(request, 'includes/email_compose_form.html', { + 'form': form, + 'job': job, + 'candidate': candidate + }) + + else: + # GET request - show the form + form = CandidateEmailForm(job, candidate) + + return render(request, 'includes/email_compose_form.html', { + 'form': form, + 'job': job, + 'candidate': candidate + }) diff --git a/templates/base.html b/templates/base.html index c87c5e1..38eec00 100644 --- a/templates/base.html +++ b/templates/base.html @@ -133,7 +133,7 @@ data-bs-auto-close="outside" data-bs-offset="0, 16" {# Vertical offset remains 16px to prevent clipping #} > - {% if user.profile.profile_image %} + {% if user.profile and user.profile.profile_image %} {{ user.username }} @@ -151,7 +151,7 @@
      • - {% if user.profile.profile_image %} + {% if user.profile and user.profile.profile_image %} {{ user.username }} diff --git a/templates/emails/interview_invitation.html b/templates/emails/interview_invitation.html new file mode 100644 index 0000000..0f8569d --- /dev/null +++ b/templates/emails/interview_invitation.html @@ -0,0 +1,139 @@ + + + + + Interview Invitation + + + +
        +
        +

        Interview Confirmation

        +
        + +

        Dear {{ candidate_name }},

        +

        Thank you for your interest in the position. We are pleased to invite you to a virtual interview. Please find the details below.

        + +

        Interview Details

        +
        + Topic: {{ meeting_topic }} +
        +
        + Date & Time: {{ meeting_date_time }} +
        +
        + Duration: {{ meeting_duration }} +
        + + {% if join_url %} + + Join Interview Now + +

        Please click the button above to join the meeting at the scheduled time.

        + {% endif %} + +

        Your Information

        +
        + Name: {{ candidate_name }} +
        +
        + Email: {{ candidate_email }} +
        + {% if candidate_phone %} +
        + Phone: {{ candidate_phone }} +
        + {% endif %} + + {% if job_title %} +

        Position Details

        +
        + Position: {{ job_title }} +
        + {% if department %} +
        + Department: {{ department }} +
        + {% endif %} + {% endif %} + + +
        + + diff --git a/templates/includes/email_compose_form.html b/templates/includes/email_compose_form.html new file mode 100644 index 0000000..1a4dcf2 --- /dev/null +++ b/templates/includes/email_compose_form.html @@ -0,0 +1,509 @@ +{% load i18n %} + +
        +
        +
        +
        +
        +
        + + {% trans "Compose Email" %} +
        +
        +
        +
        + {% csrf_token %} + + +
        + + {{ form.subject }} + {% if form.subject.errors %} +
        + {% for error in form.subject.errors %} + {{ error }} + {% endfor %} +
        + {% endif %} +
        + + +
        + +
        + {% for choice in form.recipients %} +
        + {{ choice }} +
        + {% endfor %} +
        + {% if form.recipients.errors %} +
        + {% for error in form.recipients.errors %} + {{ error }} + {% endfor %} +
        + {% endif %} +
        + + +
        + + {{ form.message }} + {% if form.message.errors %} +
        + {% for error in form.message.errors %} + {{ error }} + {% endfor %} +
        + {% endif %} +
        + + +
        +
        +
        +
        + + +
        +
        +
        +
        + + +
        +
        +
        +
        + + + +
        +
        + + {% trans "Email will be sent to all selected recipients" %} +
        +
        + + +
        +
        +
        +
        +
        +
        +
        + + +
        +
        +
        +
        + {% trans "Loading..." %} +
        +
        + {% trans "Sending email..." %} +
        +
        +
        +
        + + +
        +
        + + + + -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/templates/recruitment/candidate_interview_view.html b/templates/recruitment/candidate_interview_view.html index 4f06570..bbb560e 100644 --- a/templates/recruitment/candidate_interview_view.html +++ b/templates/recruitment/candidate_interview_view.html @@ -231,13 +231,14 @@ {% trans "Schedule Interviews" %} -
        +
        - +
        {% endif %}
        @@ -369,6 +370,14 @@ title="View Profile"> + {% if candidate.get_latest_meeting %}
        - +

    - + + + + {% endblock %} {% block customJS %} @@ -579,7 +608,7 @@ $(document).ready(function() { // Check the flag passed from the Django view var shouldOpenModal = {{ show_modal_on_load|yesno:"true,false" }}; - + // If the view detected an invalid form submission (POST request), open the modal if (shouldOpenModal) { // Use the native Bootstrap 5 JS function to show the modal diff --git a/test_async_email.py b/test_async_email.py new file mode 100644 index 0000000..a90c1d0 --- /dev/null +++ b/test_async_email.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +""" +Test script for async email functionality +""" + +import os +import sys +import django + +# Setup Django +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'NorahUniversity.settings') +django.setup() + +from django.contrib.auth.models import User +from recruitment.email_service import send_bulk_email +from recruitment.models import JobPosting, Candidate + +def test_async_email(): + """Test async email sending functionality""" + + print("🧪 Testing Async Email Functionality") + print("=" * 50) + + try: + # Get a test user + test_user = User.objects.first() + if not test_user: + print("❌ No users found in database. Please create a user first.") + return + + # Get a test job and candidate + test_job = JobPosting.objects.first() + test_candidate = Candidate.objects.first() + + if not test_job or not test_candidate: + print("❌ No test job or candidate found. Please create some test data first.") + return + + print(f"📧 Test User: {test_user.email}") + print(f"💼 Test Job: {test_job.title}") + print(f"👤 Test Candidate: {test_candidate.name}") + + # Test synchronous email sending + print("\n1. Testing Synchronous Email Sending...") + try: + sync_result = send_bulk_email( + subject="Test Synchronous Email", + message="This is a test synchronous email from the ATS system.", + recipient_list=[test_user.email], + async_task=False + ) + print(f" ✅ Sync result: {sync_result}") + except Exception as e: + print(f" ❌ Sync error: {e}") + + # Test asynchronous email sending + print("\n2. Testing Asynchronous Email Sending...") + try: + async_result = send_bulk_email( + subject="Test Asynchronous Email", + message="This is a test asynchronous email from the ATS system.", + recipient_list=[test_user.email], + async_task=True + ) + print(f" ✅ Async result: {async_result}") + except Exception as e: + print(f" ❌ Async error: {e}") + + print("\n3. Testing Email Service Status...") + + # Check Django Q configuration + try: + import django_q + from django_q.models import Task + pending_tasks = Task.objects.count() + print(f" 📊 Django Q Status: Installed, {pending_tasks} tasks in queue") + except ImportError: + print(" ⚠️ Django Q not installed") + except Exception as e: + print(f" 📊 Django Q Status: Installed but error checking status: {e}") + + # Check email backend configuration + from django.conf import settings + email_backend = getattr(settings, 'EMAIL_BACKEND', 'not configured') + print(f" 📧 Email Backend: {email_backend}") + + email_host = getattr(settings, 'EMAIL_HOST', 'not configured') + print(f" 🌐 Email Host: {email_host}") + + email_port = getattr(settings, 'EMAIL_PORT', 'not configured') + print(f" 🔌 Email Port: {email_port}") + + print("\n✅ Async email functionality test completed!") + print("💡 If emails are not being received, check:") + print(" - Email server configuration in settings.py") + print(" - Django Q cluster status (python manage.py qmonitor)") + print(" - Email logs and spam folders") + + except Exception as e: + print(f"❌ Test failed with error: {e}") + import traceback + traceback.print_exc() + +if __name__ == "__main__": + test_async_email() diff --git a/test_email_attachments.py b/test_email_attachments.py new file mode 100644 index 0000000..040d695 --- /dev/null +++ b/test_email_attachments.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +""" +Test script for email attachment functionality +""" + +import os +import django +from django.conf import settings +from django.test import TestCase, Client +from django.core.files.uploadedfile import SimpleUploadedFile +from django.core.files.base import ContentFile +import io +from unittest.mock import Mock +from recruitment.email_service import send_bulk_email +from recruitment.forms import CandidateEmailForm +from recruitment.models import JobPosting, Candidate +from django.test import RequestFactory +from django.contrib.auth.models import User + +# Configure Django settings +if not settings.configured: + settings.configure( + DEBUG=True, + DATABASES={ + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': ':memory:', + } + }, + USE_TZ=True, + SECRET_KEY='test-secret-key', + INSTALLED_APPS=[ + 'django.contrib.contenttypes', + 'django.contrib.auth', + 'django.contrib.sessions', + 'recruitment', + ], + EMAIL_BACKEND='django.core.mail.backends.console.EmailBackend', + ) + +# Setup test database +from django.db import connection +from django.core.management import execute_from_command_line + +def setup_test_data(): + """Create test data for email attachment testing""" + # Create test user + user = User.objects.create_user( + username='testuser', + email='test@example.com', + first_name='Test', + last_name='User' + ) + + # Create test job + job = JobPosting.objects.create( + title='Test Job Position', + description='This is a test job for email attachment testing.', + status='ACTIVE', + internal_job_id='TEST-001' + ) + + # Create test candidate + candidate = Candidate.objects.create( + first_name='John', + last_name='Doe', + email='john.doe@example.com', + phone='+1234567890', + address='123 Test Street', + job=job, + stage='Interview' + ) + + return user, job, candidate + +def test_email_service_with_attachments(): + """Test the email service directly with attachments""" + print("Testing email service with attachments...") + + # Create test files + test_files = [] + + # Test 1: Simple text file + text_content = "This is a test attachment content." + text_file = ContentFile( + text_content.encode('utf-8'), + name='test_document.txt' + ) + test_files.append(('test_document.txt', text_file, 'text/plain')) + + # Test 2: PDF content (simulated) + pdf_content = b'%PDF-1.4\n1 0 obj\n<<\n/Length 100\n>>stream\nxref\nstartxref\n1234\n5678\n/ModDate(D:20250101)\n' + pdf_file = ContentFile( + pdf_content, + name='test_document.pdf' + ) + test_files.append(('test_document.pdf', pdf_file, 'application/pdf')) + + # Test 3: Image file (simulated) + image_content = b'\x89PNG\r\n\x8a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 diff --git a/test_email_attachments_clean.py b/test_email_attachments_clean.py new file mode 100644 index 0000000..15c50ea --- /dev/null +++ b/test_email_attachments_clean.py @@ -0,0 +1,267 @@ +#!/usr/bin/env python +""" +Clean test script for email attachment functionality +""" + +import os +import sys +import django +from django.conf import settings + +# Configure Django settings BEFORE importing any Django modules +if not settings.configured: + settings.configure( + DEBUG=True, + DATABASES={ + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': ':memory:', + } + }, + USE_TZ=True, + SECRET_KEY='test-secret-key', + INSTALLED_APPS=[ + 'django.contrib.contenttypes', + 'django.contrib.auth', + 'django.contrib.sessions', + 'recruitment', + ], + EMAIL_BACKEND='django.core.mail.backends.console.EmailBackend', + MEDIA_ROOT='/tmp/test_media', + FILE_UPLOAD_TEMP_DIR='/tmp/test_uploads', + ) + +# Setup Django +django.setup() + +# Now import Django modules +from django.test import TestCase, Client +from django.core.files.uploadedfile import SimpleUploadedFile +from django.core.files.base import ContentFile +import io +from unittest.mock import Mock +from recruitment.email_service import send_bulk_email +from recruitment.forms import CandidateEmailForm +from recruitment.models import JobPosting, Candidate +from django.test import RequestFactory +from django.contrib.auth.models import User + +# Setup test database +from django.db import connection +from django.core.management import execute_from_command_line + +def setup_test_data(): + """Create test data for email attachment testing""" + # Create test user + user = User.objects.create_user( + username='testuser', + email='test@example.com', + first_name='Test', + last_name='User' + ) + + # Create test job + job = JobPosting.objects.create( + title='Test Job Position', + description='This is a test job for email attachment testing.', + status='ACTIVE', + internal_job_id='TEST-001' + ) + + # Create test candidate + candidate = Candidate.objects.create( + first_name='John', + last_name='Doe', + email='john.doe@example.com', + phone='+1234567890', + address='123 Test Street', + job=job, + stage='Interview' + ) + + return user, job, candidate + +def test_email_service_with_attachments(): + """Test the email service directly with attachments""" + print("Testing email service with attachments...") + + # Create test files + test_files = [] + + # Test 1: Simple text file + text_content = "This is a test attachment content." + text_file = ContentFile( + text_content.encode('utf-8'), + name='test_document.txt' + ) + test_files.append(('test_document.txt', text_file, 'text/plain')) + + # Test 2: PDF content (simulated) + pdf_content = b'%PDF-1.4\n1 0 obj\n<<\n/Length 100\n>>stream\nxref\nstartxref\n1234\n5678\n/ModDate(D:20250101)\n' + pdf_file = ContentFile( + pdf_content, + name='test_document.pdf' + ) + test_files.append(('test_document.pdf', pdf_file, 'application/pdf')) + + # Test 3: Image file (simulated PNG header) + image_content = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01' + image_file = ContentFile( + image_content, + name='test_image.png' + ) + test_files.append(('test_image.png', image_file, 'image/png')) + + try: + # Test email service with attachments + result = send_bulk_email( + subject='Test Email with Attachments', + body='This is a test email with attachments.', + from_email='test@example.com', + recipient_list=['recipient@example.com'], + attachments=test_files + ) + + print(f"Email service result: {result}") + print("✓ Email service with attachments test passed") + return True + + except Exception as e: + print(f"✗ Email service test failed: {e}") + return False + +def test_candidate_email_form_with_attachments(): + """Test the CandidateEmailForm with attachments""" + print("\nTesting CandidateEmailForm with attachments...") + + user, job, candidate = setup_test_data() + + # Create test files for form + text_file = SimpleUploadedFile( + "test.txt", + b"This is test content for form attachment" + ) + + pdf_file = SimpleUploadedFile( + "test.pdf", + b"%PDF-1.4 test content" + ) + + form_data = { + 'subject': 'Test Subject', + 'body': 'Test body content', + 'from_email': 'test@example.com', + 'recipient_list': 'recipient@example.com', + } + + files_data = { + 'attachments': [text_file, pdf_file] + } + + try: + form = CandidateEmailForm(data=form_data, files=files_data) + + if form.is_valid(): + print("✓ Form validation passed") + print(f"Form cleaned data: {form.cleaned_data}") + + # Test form processing + try: + result = form.save() + print(f"✓ Form save result: {result}") + return True + except Exception as e: + print(f"✗ Form save failed: {e}") + return False + else: + print(f"✗ Form validation failed: {form.errors}") + return False + + except Exception as e: + print(f"✗ Form test failed: {e}") + return False + +def test_email_view_with_attachments(): + """Test the email view with attachments""" + print("\nTesting email view with attachments...") + + user, job, candidate = setup_test_data() + factory = RequestFactory() + + # Create a mock request with files + text_file = SimpleUploadedFile( + "test.txt", + b"This is test content for view attachment" + ) + + request = factory.post( + '/recruitment/send-candidate-email/', + data={ + 'subject': 'Test Subject', + 'body': 'Test body content', + 'from_email': 'test@example.com', + 'recipient_list': 'recipient@example.com', + }, + format='multipart' + ) + request.FILES['attachments'] = [text_file] + request.user = user + + try: + # Import and test the view + from recruitment.views import send_candidate_email + + response = send_candidate_email(request) + print(f"View response status: {response.status_code}") + + if response.status_code == 200: + print("✓ Email view test passed") + return True + else: + print(f"✗ Email view test failed with status: {response.status_code}") + return False + + except Exception as e: + print(f"✗ Email view test failed: {e}") + return False + +def main(): + """Run all email attachment tests""" + print("=" * 60) + print("EMAIL ATTACHMENT FUNCTIONALITY TESTS") + print("=" * 60) + + # Initialize Django + django.setup() + + # Create tables + from django.core.management import execute_from_command_line + execute_from_command_line(['manage.py', 'migrate', '--run-syncdb']) + + results = [] + + # Run tests + results.append(test_email_service_with_attachments()) + results.append(test_candidate_email_form_with_attachments()) + results.append(test_email_view_with_attachments()) + + # Summary + print("\n" + "=" * 60) + print("TEST SUMMARY") + print("=" * 60) + + passed = sum(results) + total = len(results) + + print(f"Tests passed: {passed}/{total}") + + if passed == total: + print("🎉 All email attachment tests passed!") + return True + else: + print("❌ Some email attachment tests failed!") + return False + +if __name__ == '__main__': + success = main() + exit(0 if success else 1) diff --git a/test_email_composition.py b/test_email_composition.py new file mode 100644 index 0000000..6e540b6 --- /dev/null +++ b/test_email_composition.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python3 +""" +Test script to verify email composition functionality +""" + +import os +import sys +import django + +# Setup Django environment +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'NorahUniversity.settings') +django.setup() + +from django.test import TestCase, Client +from django.urls import reverse +from django.contrib.auth.models import User +from django.utils import timezone +from recruitment.models import JobPosting, Candidate +from unittest.mock import patch, MagicMock + +def test_email_composition_view(): + """Test the email composition view""" + print("Testing email composition view...") + + # Create test user (delete if exists) + User.objects.filter(username='testuser').delete() + user = User.objects.create_user( + username='testuser', + email='test@example.com', + password='testpass123' + ) + + # Create test job + job = JobPosting.objects.create( + title='Test Job', + internal_job_id='TEST001', + description='Test job description', + status='active', + application_deadline=timezone.now() + timezone.timedelta(days=30) + ) + + # Add user to job participants so they appear in recipient choices + job.users.add(user) + + # Create test candidate + candidate = Candidate.objects.create( + first_name='Test Candidate', + last_name='', + email='candidate@example.com', + phone='1234567890', + job=job + ) + + # Create client and login + client = Client() + client.login(username='testuser', password='testpass123') + + # Test GET request to email composition view + url = reverse('compose_candidate_email', kwargs={ + 'job_slug': job.slug, + 'candidate_slug': candidate.slug + }) + + try: + response = client.get(url) + print(f"✓ GET request successful: {response.status_code}") + + if response.status_code == 200: + print("✓ Email composition form rendered successfully") + + # Check if form contains expected fields + content = response.content.decode('utf-8') + if 'subject' in content.lower(): + print("✓ Subject field found in form") + if 'message' in content.lower(): + print("✓ Message field found in form") + if 'recipients' in content.lower(): + print("✓ Recipients field found in form") + + else: + print(f"✗ Unexpected status code: {response.status_code}") + + except Exception as e: + print(f"✗ Error testing GET request: {e}") + + # Test POST request with mock email sending + post_data = { + 'subject': 'Test Subject', + 'message': 'Test message content', + 'recipients': ['candidate@example.com'], + 'include_candidate_info': True, + 'include_meeting_details': False + } + + with patch('django.core.mail.send_mass_mail') as mock_send_mail: + mock_send_mail.return_value = 1 + + try: + response = client.post(url, data=post_data) + print(f"✓ POST request successful: {response.status_code}") + + if response.status_code == 200: + # Check if JSON response is correct + try: + json_data = response.json() + if json_data.get('success'): + print("✓ Email sent successfully") + print(f"✓ Success message: {json_data.get('message')}") + else: + print(f"✗ Email send failed: {json_data.get('error')}") + except: + print("✗ Invalid JSON response") + else: + print(f"✗ Unexpected status code: {response.status_code}") + + except Exception as e: + print(f"✗ Error testing POST request: {e}") + + # Clean up + user.delete() + job.delete() + candidate.delete() + + print("Email composition test completed!") + +def test_email_form(): + """Test the CandidateEmailForm""" + print("\nTesting CandidateEmailForm...") + + from recruitment.forms import CandidateEmailForm + + # Create test user for form (delete if exists) + User.objects.filter(username='formuser').delete() + form_user = User.objects.create_user( + username='formuser', + email='form@example.com', + password='formpass123' + ) + + # Create test job and candidate for form + job = JobPosting.objects.create( + title='Test Job Form', + internal_job_id='TEST002', + description='Test job description for form', + status='active', + application_deadline=timezone.now() + timezone.timedelta(days=30) + ) + + # Add user to job participants so they appear in recipient choices + job.users.add(form_user) + + candidate = Candidate.objects.create( + first_name='Test Candidate', + last_name='Form', + email='candidate_form@example.com', + phone='1234567890', + job=job + ) + + try: + # Test valid form data - get available choices from form + form = CandidateEmailForm(job, candidate) + available_choices = [choice[0] for choice in form.fields['recipients'].choices] + + # Use first available choice for testing + test_recipient = available_choices[0] if available_choices else None + + if test_recipient: + form = CandidateEmailForm(job, candidate, data={ + 'subject': 'Test Subject', + 'message': 'Test message content', + 'recipients': [test_recipient], + 'include_candidate_info': True, + 'include_meeting_details': False + }) + + if form.is_valid(): + print("✓ Form validation passed") + print(f"✓ Cleaned recipients: {form.cleaned_data['recipients']}") + else: + print(f"✗ Form validation failed: {form.errors}") + else: + print("✗ No recipient choices available for testing") + except Exception as e: + print(f"✗ Error testing form: {e}") + + try: + # Test invalid form data (empty subject) + form = CandidateEmailForm(job, candidate, data={ + 'subject': '', + 'message': 'Test message content', + 'recipients': [], + 'include_candidate_info': True, + 'include_meeting_details': False + }) + + if not form.is_valid(): + print("✓ Form correctly rejected empty subject") + if 'subject' in form.errors: + print("✓ Subject field has validation error") + else: + print("✗ Form should have failed validation") + except Exception as e: + print(f"✗ Error testing invalid form: {e}") + + # Clean up + job.delete() + candidate.delete() + +if __name__ == '__main__': + print("Running Email Composition Tests") + print("=" * 50) + + test_email_form() + test_email_composition_view() + + print("\n" + "=" * 50) + print("All tests completed!") diff --git a/test_email_form_js.html b/test_email_form_js.html new file mode 100644 index 0000000..edc579f --- /dev/null +++ b/test_email_form_js.html @@ -0,0 +1,507 @@ + + + + + + Email Compose Form Test + + + + +
    +

    Email Compose Form JavaScript Test

    + + +
    +
    +
    +
    +
    +
    + + Compose Email +
    +
    +
    +
    + + + +
    + + +
    + + +
    + +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    + + +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    + + Email will be sent to all selected recipients +
    +
    + + +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + Loading... +
    +
    + Sending email... +
    +
    +
    +
    + + +
    +
    + + +
    +

    Test Results

    +
    +
    +
    + + + + + + + diff --git a/test_html_email_template.py b/test_html_email_template.py new file mode 100644 index 0000000..657be5d --- /dev/null +++ b/test_html_email_template.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python +""" +Test script for HTML email template functionality +""" + +import os +import sys +import django + +# Setup Django +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'NorahUniversity.settings') +django.setup() + +from django.template.loader import render_to_string +from django.utils.html import strip_tags +from recruitment.models import Candidate, JobPosting +from recruitment.email_service import send_interview_invitation_email + +def test_html_template(): + """Test the HTML email template rendering""" + print("Testing HTML email template...") + + # Create test context + context = { + 'candidate_name': 'John Doe', + 'candidate_email': 'john.doe@example.com', + 'candidate_phone': '+966 50 123 4567', + 'job_title': 'Senior Software Developer', + 'department': 'Information Technology', + 'company_name': 'Norah University', + 'meeting_topic': 'Interview for Senior Software Developer', + 'meeting_date_time': 'November 15, 2025 at 2:00 PM', + 'meeting_duration': '60 minutes', + 'join_url': 'https://zoom.us/j/123456789', + } + + try: + # Test template rendering + html_content = render_to_string('emails/interview_invitation.html', context) + plain_content = strip_tags(html_content) + + print("✅ HTML template rendered successfully!") + print(f"HTML content length: {len(html_content)} characters") + print(f"Plain text length: {len(plain_content)} characters") + + # Save rendered HTML to file for inspection + with open('test_interview_email.html', 'w', encoding='utf-8') as f: + f.write(html_content) + print("✅ HTML content saved to 'test_interview_email.html'") + + # Save plain text to file for inspection + with open('test_interview_email.txt', 'w', encoding='utf-8') as f: + f.write(plain_content) + print("✅ Plain text content saved to 'test_interview_email.txt'") + + return True + + except Exception as e: + print(f"❌ Error rendering template: {e}") + return False + +def test_email_service_function(): + """Test the email service function with mock data""" + print("\nTesting email service function...") + + try: + # Get a real candidate and job for testing + candidate = Candidate.objects.first() + job = JobPosting.objects.first() + + if not candidate: + print("❌ No candidates found in database") + return False + + if not job: + print("❌ No jobs found in database") + return False + + print(f"Using candidate: {candidate.name}") + print(f"Using job: {job.title}") + + # Test meeting details + meeting_details = { + 'topic': f'Interview for {job.title}', + 'date_time': 'November 15, 2025 at 2:00 PM', + 'duration': '60 minutes', + 'join_url': 'https://zoom.us/j/test123456', + } + + # Test the email function (without actually sending) + result = send_interview_invitation_email( + candidate=candidate, + job=job, + meeting_details=meeting_details, + recipient_list=['test@example.com'] + ) + + if result['success']: + print("✅ Email service function executed successfully!") + print(f"Recipients: {result.get('recipients_count', 'N/A')}") + print(f"Message: {result.get('message', 'N/A')}") + else: + print(f"❌ Email service function failed: {result.get('error', 'Unknown error')}") + + return result['success'] + + except Exception as e: + print(f"❌ Error testing email service: {e}") + return False + +def test_template_variables(): + """Test all template variables""" + print("\nTesting template variables...") + + # Test with minimal data + minimal_context = { + 'candidate_name': 'Test Candidate', + 'candidate_email': 'test@example.com', + 'job_title': 'Test Position', + } + + try: + html_content = render_to_string('emails/interview_invitation.html', minimal_context) + print("✅ Template works with minimal data") + + # Check for required variables + required_vars = ['candidate_name', 'candidate_email', 'job_title'] + missing_vars = [] + + for var in required_vars: + if f'{{ {var} }}' in html_content: + missing_vars.append(var) + + if missing_vars: + print(f"⚠️ Missing variables: {missing_vars}") + else: + print("✅ All required variables are present") + + return True + + except Exception as e: + print(f"❌ Error with minimal data: {e}") + return False + +def main(): + """Run all tests""" + print("🧪 Testing HTML Email Template System") + print("=" * 50) + + # Test 1: Template rendering + test1_passed = test_html_template() + + # Test 2: Template variables + test2_passed = test_template_variables() + + # Test 3: Email service function + test3_passed = test_email_service_function() + + # Summary + print("\n" + "=" * 50) + print("📊 TEST SUMMARY") + print(f"Template Rendering: {'✅ PASS' if test1_passed else '❌ FAIL'}") + print(f"Template Variables: {'✅ PASS' if test2_passed else '❌ FAIL'}") + print(f"Email Service: {'✅ PASS' if test3_passed else '❌ FAIL'}") + + overall_success = test1_passed and test2_passed and test3_passed + print(f"\nOverall Result: {'✅ ALL TESTS PASSED' if overall_success else '❌ SOME TESTS FAILED'}") + + if overall_success: + print("\n🎉 HTML email template system is ready!") + print("You can now send professional interview invitations using the new template.") + else: + print("\n🔧 Please fix the issues before using the template system.") + +if __name__ == '__main__': + main() diff --git a/test_interview_email.html b/test_interview_email.html new file mode 100644 index 0000000..6f84efb --- /dev/null +++ b/test_interview_email.html @@ -0,0 +1,139 @@ + + + + + Interview Invitation + + + +
    +
    +

    Interview Confirmation

    +
    + +

    Dear John Doe,

    +

    Thank you for your interest in the position. We are pleased to invite you to a virtual interview. Please find the details below.

    + +

    Interview Details

    +
    + Topic: Interview for Senior Software Developer +
    +
    + Date & Time: November 15, 2025 at 2:00 PM +
    +
    + Duration: 60 minutes +
    + + + + Join Interview Now + +

    Please click the button above to join the meeting at the scheduled time.

    + + +

    Your Information

    +
    + Name: John Doe +
    +
    + Email: john.doe@example.com +
    + +
    + Phone: +966 50 123 4567 +
    + + + +

    Position Details

    +
    + Position: Senior Software Developer +
    + +
    + Department: Information Technology +
    + + + + +
    + + diff --git a/test_interview_email.txt b/test_interview_email.txt new file mode 100644 index 0000000..5c42c4c --- /dev/null +++ b/test_interview_email.txt @@ -0,0 +1,139 @@ + + + + + Interview Invitation + + /* Basic reset and typography */ + body { + font-family: Arial, sans-serif; + line-height: 1.6; + color: #333333; + margin: 0; + padding: 0; + background-color: #f4f4f4; + } + /* Container for the main content */ + .container { + max-width: 600px; + margin: 20px auto; + background-color: #ffffff; + padding: 30px; + border-radius: 8px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + } + /* Header styling */ + .header { + text-align: center; + border-bottom: 2px solid #007bff; + padding-bottom: 10px; + margin-bottom: 20px; + } + .header h1 { + color: #007bff; + font-size: 24px; + margin: 0; + } + /* Section headings */ + .section-header { + color: #007bff; + font-size: 18px; + margin-top: 25px; + margin-bottom: 10px; + border-left: 4px solid #007bff; + padding-left: 10px; + } + /* Key detail rows */ + .detail-row { + margin-bottom: 10px; + } + .detail-row strong { + display: inline-block; + width: 120px; + color: #555555; + } + /* Button style for the Join URL */ + .button { + display: block; + width: 80%; + margin: 25px auto; + padding: 12px 0; + background-color: #28a745; /* Success/Go color */ + color: #ffffff; + text-align: center; + text-decoration: none; + border-radius: 5px; + font-weight: bold; + font-size: 16px; + } + /* Footer/closing section */ + .footer { + margin-top: 30px; + padding-top: 15px; + border-top: 1px dashed #cccccc; + text-align: center; + font-size: 14px; + color: #777777; + } + + + + + + Interview Confirmation + + + Dear John Doe, + Thank you for your interest in the position. We are pleased to invite you to a virtual interview. Please find the details below. + + Interview Details + + Topic: Interview for Senior Software Developer + + + Date & Time: November 15, 2025 at 2:00 PM + + + Duration: 60 minutes + + + + + Join Interview Now + + Please click the button above to join the meeting at the scheduled time. + + + Your Information + + Name: John Doe + + + Email: john.doe@example.com + + + + Phone: +966 50 123 4567 + + + + + Position Details + + Position: Senior Software Developer + + + + Department: Information Technology + + + + + + We look forward to speaking with you. + If you have any questions, please reply to this email. + Best regards,The Norah University Team + + + + diff --git a/test_simple_email.py b/test_simple_email.py new file mode 100644 index 0000000..b748cc5 --- /dev/null +++ b/test_simple_email.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python +""" +Simple test script for basic email functionality without attachments +""" + +import os +import sys +import django +from django.conf import settings + +# Configure Django settings BEFORE importing any Django modules +if not settings.configured: + settings.configure( + DEBUG=True, + DATABASES={ + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': ':memory:', + } + }, + USE_TZ=True, + SECRET_KEY='test-secret-key', + INSTALLED_APPS=[ + 'django.contrib.contenttypes', + 'django.contrib.auth', + 'django.contrib.sessions', + 'recruitment', + ], + EMAIL_BACKEND='django.core.mail.backends.console.EmailBackend', + ) + +# Setup Django +django.setup() + +# Now import Django modules +from django.test import TestCase, Client +from django.test import RequestFactory +from django.contrib.auth.models import User +from recruitment.email_service import send_bulk_email +from recruitment.forms import CandidateEmailForm +from recruitment.models import JobPosting, Candidate, Participants + +def setup_test_data(): + """Create test data for email testing""" + # Create test user (get or create to avoid duplicates) + user, created = User.objects.get_or_create( + username='testuser', + defaults={ + 'email': 'test@example.com', + 'first_name': 'Test', + 'last_name': 'User' + } + ) + + # Create test job + from datetime import datetime, timedelta + job = JobPosting.objects.create( + title='Test Job Position', + description='This is a test job for email testing.', + status='ACTIVE', + internal_job_id='TEST-001', + application_deadline=datetime.now() + timedelta(days=30) + ) + + # Create test candidate + candidate = Candidate.objects.create( + first_name='John', + last_name='Doe', + email='john.doe@example.com', + phone='+1234567890', + address='123 Test Street', + job=job, + stage='Interview' + ) + + # Create test participants + participant1 = Participants.objects.create( + name='Alice Smith', + email='alice@example.com', + phone='+1234567891', + designation='Interviewer' + ) + + participant2 = Participants.objects.create( + name='Bob Johnson', + email='bob@example.com', + phone='+1234567892', + designation='Hiring Manager' + ) + + # Add participants to job + job.participants.add(participant1, participant2) + + return user, job, candidate, [participant1, participant2] + +def test_email_service_basic(): + """Test the email service with basic functionality""" + print("Testing basic email service...") + + try: + # Test email service without attachments + result = send_bulk_email( + subject='Test Basic Email', + message='This is a test email without attachments.', + recipient_list=['recipient1@example.com', 'recipient2@example.com'] + ) + + print(f"Email service result: {result}") + print("✓ Basic email service test passed") + return True + + except Exception as e: + print(f"✗ Basic email service test failed: {e}") + return False + +def test_candidate_email_form_basic(): + """Test the CandidateEmailForm without attachments""" + print("\nTesting CandidateEmailForm without attachments...") + + user, job, candidate, participants = setup_test_data() + + form_data = { + 'subject': 'Test Subject', + 'message': 'Test body content', + 'recipients': [f'participant_{p.id}' for p in participants], + 'include_candidate_info': True, + 'include_meeting_details': True, + } + + try: + form = CandidateEmailForm(data=form_data, job=job, candidate=candidate) + + if form.is_valid(): + print("✓ Form validation passed") + print(f"Form cleaned data keys: {list(form.cleaned_data.keys())}") + + # Test getting email addresses + email_addresses = form.get_email_addresses() + print(f"Email addresses: {email_addresses}") + + # Test getting formatted message + formatted_message = form.get_formatted_message() + print(f"Formatted message length: {len(formatted_message)} characters") + + return True + else: + print(f"✗ Form validation failed: {form.errors}") + return False + + except Exception as e: + print(f"✗ Form test failed: {e}") + return False + +def test_email_sending_workflow(): + """Test the complete email sending workflow""" + print("\nTesting complete email sending workflow...") + + user, job, candidate, participants = setup_test_data() + + form_data = { + 'subject': 'Interview Update: John Doe - Test Job Position', + 'message': 'Please find the interview update below.', + 'recipients': [f'participant_{p.id}' for p in participants], + 'include_candidate_info': True, + 'include_meeting_details': True, + } + + try: + # Create and validate form + form = CandidateEmailForm(data=form_data, job=job, candidate=candidate) + + if not form.is_valid(): + print(f"✗ Form validation failed: {form.errors}") + return False + + # Get email data + subject = form.cleaned_data['subject'] + message = form.get_formatted_message() + recipient_emails = form.get_email_addresses() + + print(f"Subject: {subject}") + print(f"Recipients: {recipient_emails}") + print(f"Message preview: {message[:200]}...") + + # Send email using service + result = send_bulk_email( + subject=subject, + message=message, + recipient_list=recipient_emails + ) + + print(f"Email sending result: {result}") + print("✓ Complete email workflow test passed") + return True + + except Exception as e: + print(f"✗ Email workflow test failed: {e}") + return False + +def main(): + """Run all simple email tests""" + print("=" * 60) + print("SIMPLE EMAIL FUNCTIONALITY TESTS") + print("=" * 60) + + # Initialize Django + django.setup() + + # Create tables + from django.core.management import execute_from_command_line + execute_from_command_line(['manage.py', 'migrate', '--run-syncdb']) + + results = [] + + # Run tests + results.append(test_email_service_basic()) + results.append(test_candidate_email_form_basic()) + results.append(test_email_sending_workflow()) + + # Summary + print("\n" + "=" * 60) + print("TEST SUMMARY") + print("=" * 60) + + passed = sum(results) + total = len(results) + + print(f"Tests passed: {passed}/{total}") + + if passed == total: + print("🎉 All simple email tests passed!") + return True + else: + print("❌ Some simple email tests failed!") + return False + +if __name__ == '__main__': + success = main() + exit(0 if success else 1)