123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151moduletypeMech=Auth.ClientmoduleStable=structopenCore.Core_stablemoduleLogin=structmoduleV1=structtypet={on_behalf_of:stringoption[@sexp.option];username:string;password:string}[@@derivingsexp]endendmoduleV1=structtypet={username:string;password:string}[@@derivingsexp]endmoduleV2=structtypeelt=|LoginofLogin.V1.t|Anon[@@derivingsexp]typet=eltlist[@@derivingsexp]letof_v1{V1.username;password}=letlogin={Login.V1.on_behalf_of=None;username;password}in[Loginlogin];;endmoduleV3=structtypemech=(moduleMech)(*_ stub [sexp] implementation for [mech] *)letsexp_of_mech(moduleA:Mech)=[%sexp(A.mechanism:string)]letmech_of_sexp=[%of_sexp:_]typeelt=|Anon|LoginofLogin.V1.t|Customofmech[@@derivingsexp]typet=eltlist[@@derivingsexp]letof_v2=Core.List.map~f:(function|V2.Loginlogin->Loginlogin|V2.Anon->Anon);;endendopen!CoreopenAsync_smtp_typesmoduleLogin=structtypet=Stable.Login.V1.t={on_behalf_of:stringoption[@sexp.option];username:string;password:(string[@sexp.opaque])}[@@derivingsexp_of]endtypemech=(moduleMech)letsexp_of_mech=[%sexp_of:Stable.V3.mech]typeelt=Stable.V3.elt=|Anon|LoginofLogin.t|Customofmech[@@derivingsexp_of]letsexp_of_elt=function|Custommech->sexp_of_mechmech|elt->sexp_of_eltelt;;typet=eltlist[@@derivingsexp_of]letallows_anon=List.exists~f:(function|Login_|Custom_->false|Anon->true);;letanon=[Anon]letlogin?on_behalf_of~username~password()=[Login{Login.on_behalf_of;username;password}];;letcustommech=[Custommech]letget_methodst~tls=List.concat_mapt~f:(function|Anon->[]|Login{Login.on_behalf_of;username;password}->ifnottlsthen[]elseletmoduleCred=structleton_behalf_of=on_behalf_ofletusername=usernameletpassword=passwordendin(moduleAuth.Plain.Client(Cred):Mech)::(ifOption.is_noneon_behalf_ofthen[(moduleAuth.Login.Client(Cred):Mech)]else[])|Custom((moduleA:Mech)asmech)->iftls||notA.require_tlsthen[mech]else[]);;letget_auth_clientt~tlsextensions=letclient_mechs=get_methodst~tlsinletserver_mechs=List.concat_mapextensions~f:(function|Smtp_extension.Authmechs->mechs|_->[])inList.find_mapserver_mechs~f:(funm->List.findclient_mechs~f:(fun(moduleM:Mech)->String.Caseless.equalmM.mechanism))|>function|Somemech->Ok(`Auth_withmech)|None->ifallows_anontthenOk`Anonelse(letclient_mechs=List.mapclient_mechs~f:(fun(moduleM:Mech)->M.mechanism)inOr_error.error_s[%sexp"No common auth mechanism available and ANON authentication not allowed by \
client",{client_mechs:stringlist;server_mechs:stringlist}]);;