....................................../////.===Shadow-Here===./////................................................ > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < ------------------------------------------------------------------------------------------------------------------- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RIFF¤ WEBPVP8 ˜ ðÑ *ôô>‘HŸK¥¤"§£±¨àð enü¹%½_F‘åè¿2ºQú³íªú`N¿­3ÿƒügµJžaÿ¯ÿ°~¼ÎùnúîÞÖô•òíôÁÉß®Sm¥Ü/ ‡ó˜f£Ùà<˜„xëJ¢Ù€SO3x<ªÔ©4¿+ç¶A`q@Ì“Úñè™ÍÿJÌ´ª-˜ÆtÊÛL]Ïq*‘Ý”ì#ŸÌÏãY]@ê`¿ /ªfkØB4·®£ó z—Üw¥Pxù–ÞLШKÇN¾AkÙTf½è'‰g gÆv›Øuh~ a˜Z— ïj*á¥t d£“uÒ ¨`K˜¹ßþ]b>˜]_ÏÔ6W—è2r4x•íÖ…"ƒÖNîä!¦å Ú}ýxGøÌ —@ ;ÆÚŠ=ɾ1ý8lªË¥ô ^yf®Œ¢u&2©nÙÇ›ñÂñŒ³ aPo['½»øFùà­+4ê“$!lövlüÞ=;N®3ð‚õ›DÉKòÞ>ÄÍ ¥ˆuߤ#ˆ$6ù™¥îЇy’ÍB¼ çxÛ;X"WL£R÷͝*ó-¶Zu}º.s¸sšXqù–DþÿvªhüïwyŸ ¯é³lÀ:KCûÄ£Ëá\…­ ~—ýóî ¼ûûÜTÓüÇy…ŽÆvc»¾×U ñ¸žþоP÷¦ó:Ò¨¨5;Ð#&#ÖúñläÿÁœ GxÉ­/ñ‡áQðìYÉtÒw޼GÔ´zàÒò ð*ëzƒ•4~H]Ø‹f ñÓÈñ`NåWçs'ÆÏW^ø¹!XžµmQ5ÃËoLœÎ: ÞËÍ¥J ù…î èo£ßPÎñ¶ž8.Œ]ʵ~5›ÙË-ù*8ÙÖß±~ ©¹rÓê‚j¶d¸{^Q'˜±Crß ÚH—#¥¥QlÀ×ëã‡DÜ«èî þ&Çæžî;ŽÏºò6ÒLÃXy&ZŒ'j‚¢Ù€IßÚù+–MGi‰*jE€‘JcÜ ÓÌ EÏÚj]o˜ Þr <¾U ûŪæÍ/šÝH¥˜b”¼ ÁñßX GP›ï2›4WŠÏà×£…íÓk†¦H·ÅíMh–*nó÷à]ÁjCº€b7<ب‹¨5車bp2:Á[UªM„QŒçiNMa#<5›áËó¸HýÊ"…×Éw¹¦ì2º–x<›»a±¸3Weü®FÝ⑱ö–î–³|LPÈ~çð~Çå‡|º kD¢µÏàÆAI %1À% ¹Ò – ”ϝS¦‰4&¶£°à Öý”û_Ò Áw°A«Å€?mÇÛgHÉ/8)á¾ÛìáöŽP í¨PŸNÙµº¦‡§Ùš"ÿ«>+ªÕ`Ê÷‡‚ß Õû˜þãÇ-PÍ.¾XV‘€ dÜ"þ4¹ ±Oú‘©t¥¦FªÄÃÄ•b‚znýu½—#cDs˜ÃiÑOˆñ×QO=*IAÊ,¶ŽZƒ;‡wøXè%EÐk:F±Ú” .Ѽ+Áu&Ç`."pÈÉw o&¿dE6‘’EqTuK@Ì¥ã™À(Êk(h‰,H}RÀIXÛš3µ1©_OqÚÒJAñ$ÊÙÜ;D3çŒ[þùœh¬Ã³™ö6ç†NY".Ú‰ï[ªŸŒ '²Ð öø_¨ÂÉ9ué¶³ÒŠõTàîMØ#û¯gN‡bÙ놚X„ö …ÉeüÌ^J ‹€.œ$Æ)βÄeæW#óüßĺŸ€ ÀzwV 9oä»f4V*uB «Ë†¹ì¯žR霓æHXa=&“I4K;¯ç‹h×·"UŠ~<•╪Vêª&ÍSÃÆÅ?ÔqÎ*mTM ˜›µwêd#[C¡©§‘D<©àb†–ÁœøvH/,í:¯( ²£|4-„Æövv„Yͼ™^Á$ˆ„¢Û[6yB.åH*V¨æ?$=˜Ñ€•ñ·­(VlŸ‘ nÀt8W÷´Bûba?q9ú¶Xƒl«ÿ\ù¶’þòUÐj/õ¢Ìµ³g$ƒÎR!¸»|Oߍë’BhîÚÑ¢ñåŒJ„®„£2Ð3•ô02Nt…!£Í]Ïc½Qÿ?ˆ<&ÃA¾Ú,JˆijÌ#5yz„‰Î|ÊŽ5QÏ:‹ÐaóVÔxW—CpeÏzÐïíçôÿÅ_[hãsÐ_/ŽTÝ?BîˆííV$<¿i>²F¬_Eß¿ †bÊŒº­ÿ®Z H“C}”¬,Mp ý/Bá£w>˜YV°aƒúh+cŠ- r/[%|üUMHäQ°X»|û/@|°¥Ð !BÔ Ç¢Ä©š+Õì D«7ìN¶ŽðÔ " ƶ’ÖçtA‰Û×}{tþz­¾GÍ›k¹OEJR$ Â׃ «ëÁ"oÉôž$oUK(Ä)Ãz³Ê-‹êN[Ò3Œñbï8P 4ƒ×q¢bo|?<ÛX¬òÄͰL–±›(™ûG?ýË©ÚÄ–ÂDØÐ_Ç¡ô ¾–ÄÏø ×e8Ë©$ÄF¹Å‹ì[©óìl:F¾f´‹‹Xì²ï®\¬ôùƒ ÿat¥óèÒùHß0äe‚;ü×h:ÆWðHž=Ã8骣"kœ'Y?³}Tûè€>?0l›e1Lòñ„aæKÆw…hÖŠùW…ÈÆÄ0ši·›[pcwËþñiêíY/~-Á5˜!¿†A›™Mÿþ(±“t@â“ö2­´TG5yé]çå僳 .·ÍïçÝ7UÚ±Ð/Nè»,_Ï ùdj7\ï Wì4›„»c¸àešg#ÒÊ⥭áØo5‘?ÌdÝô¯ ¹kzsƒ=´#ëÉK›Ø´±-¥eW?‡çßtòTã…$Ý+qÿ±ƒ÷_3Ô¥í÷:æ–ž<·Ö‡‰Å¢ š‡%Ô—utÌÈìðžgÖÀz²À—ï÷Óîäõ{K'´È÷³yaÏÁjƒô}ž§®æÊydÕÈë5¯èˆõvÕ©ã*çD„ “z„Ó‡^^xÂ3M§A´JG‚öï 3W'ˆ.OvXè¡ÊÕª?5º7†˜(˜Ç¶#çê’¶!ÌdZK§æ 0fãaN]òY³RV ™î$®K2R¨`W!1Ôó\;Ý ýB%qæK•&ÓÈe9È0êI±žeŸß -ú@žQr¦ ö4»M¼Áè¹µmw 9 EÆE_°2ó„ŸXKWÁ×Hóì^´²GѝF©óäR†¦‰ç"V»eØ<3ùd3ÿÚ¤Žú“Gi" —‘_ÙËÎ~Üö¯¥½Î»üŸEÚŽåmÞþí ;ÞólËΦMzA"Âf(´òá;Éï(/7½ûñÌ­cïÕçлþÝz¾-ÍvÑ“pH­–ðÓj$¸Äû¤‚‘ãUBË-n“2åPkS5&‹Â|+g^œ®Ì͆d!OïäîU«c;{Û!ÅŽ«ëZ9Ókóˆ]¯ƒ›né `ÇÒ+tÆš (ØKá¾—=3œ®•vuMñg²\ï Ec€ 05±d™‡×iÇ×›UúvÌ¢£Èþ¡ÕØô¶ßÎA"ß±#Ö²ˆÊŸ¦*Ä~ij|àø.-¼'»Ú¥£h ofº¦‡VsR=N½„Î v˜Z*SÌ{=jÑB‹tê…;’HžH¯8–îDù8ñ¢|Q•bÛçš–‹m³“ê¨ åÏ^m¬Žãþ©ïêO‡½6] µÆ„Ooòü ²x}N¦Ë3ïé¿»€›HA˜m%çÞ/¿í7Fø“‹léUk)É°Œµ8Q8›:ÀŠeT*šõ~ôڝG6 ¢}`ùH­–”¡k ‰P1>š†®9z11!X wKfmÁ¦xÑ,N1Q”–æB¶M…ÒÃv6SMˆhU¬ÊPŽï‘öj=·CŒ¯u¹ƒVIЃsx4’ömÛýcå¡¶7ßŠß 57^\wÒÐÆ k§h,Œý î«q^R½3]J¸ÇðN ‚çU¬ôº^Áì} ³f©Õœ§ˆã:FÄÈ‚é(€™?àýÓüè1Gô£¼éj‚OÅñ  #>×—ßtà 0G¥Åa뀐kßhc™À_ÉñÞ#±)GD" YîäË-ÿÙ̪ ¹™a¯´¢E\ÝÒö‚;™„ë]_ p8‰o¡ñ+^÷ 3‘'dT4œŽ ðVë½° :¬víÑ«£tßÚS-3¶“þ2 †üüʨòrš¹M{É_¤`Û¨0ìjœøJ‡:÷ÃáZ˜†@GP&œÑDGÏs¡þ¦þDGú‘1Yá9Ôþ¼ ûø…§÷8&–ÜÑnÄ_m®^üÆ`;ÉVÁJ£?â€-ßê}suÍ2sõA NÌúA磸‘îÿÚ»ƒìö·á¿±tÑÐ"Tÿü˜[@/äj¬€uüªìù¥Ý˜á8Ý´sõj 8@rˆð äþZÇD®ÿUÏ2ùôõrBzÆÏÞž>Ì™xœ“ wiÎ×7_… ¸ \#€MɁV¶¥üÕÿPÔ9Z‡ø§É8#H:ƒ5ÀÝå9ÍIŒ5åKÙŠ÷qÄ>1AÈøžj"µÂд/ªnÀ qªã}"iŸBå˜ÓÛŽ¦…&ݧ;G@—³b¯“•"´4í¨ôM¨åñC‹ïùÉó¯ÓsSH2Ý@ßáM‡ˆKÀªÛUeø/4\gnm¥‹ŸŒ qÄ b9ÞwÒNÏ_4Ég³ú=܆‚´ •â¥õeíþkjz>éÚyU«Íӝ݃6"8/ø{=Ô¢»G¥ äUw°W«,ô—¿ãㆅү¢³xŠUû™yŒ (øSópÐ 9\åTâ»—*oG$/×ÍT†Y¿1¤Þ¢_‡ ¼ „±ÍçèSaÓ 3ÛMÁBkxs‰’R/¡¤ˆÙçª(*õ„üXÌ´ƒ E§´¬EF"Ù”R/ÐNyÆÂ^°?™6¡œïJ·±$§?º>ÖüœcNÌù¯G ‹ñ2ЁBB„^·úìaz¨k:#¨Æ¨8LÎõލ£^§S&cŒÐU€ü(‡F±Š¼&P>8ÙÁ ‰ p5?0ÊÆƒZl¸aô š¼¡}gÿ¶zÆC²¹¬ÎÖG*HB¡O<º2#ñŒAƒ–¡B˜´É$¥›É:FÀÔx¾u?XÜÏÓvN©RS{2ʈãk9rmP¼Qq̳ è¼ÐFׄ^¡Öì fE“F4A…!ì/…¦Lƒ… … $%´¾yã@CI¬ á—3PþBÏNÿ<ý°4Ü ËÃ#ØÍ~âW«rEñw‹eùMMHß²`¬Öó½íf³:‹k˜¯÷}Z!ã¿<¥,\#öµÀ¯aÒNÆIé,Ћ–lŽ#Àæ9ÀÒS·I’½-Ïp Äz¤Š Â* ­íÄ9­< h>׍3ZkËU¹§˜ŒŠ±f­’¤º³Q ÏB?‹#µíÃ¥®@(Gs«†vI¥Mµ‹Á©e~2ú³ÁP4ìÕi‚²Ê^ö@-DþÓàlÜOÍ]n"µã:žpsŽ¢:! Aõ.ç~ÓBûH÷JCÌ]õVƒd «ú´QÙEA–¯¯Œ!.ˆˆëQ±ù œ·Ì!Õâ )ùL„ÅÀlÚè5@B…o´Æ¸XÓ&Û…O«˜”_#‡ƒ„ûÈt!¤ÁÏ›ÎÝŠ?c9 â\>lÓÁVÄÑ™£eØY]:fÝ–—ù+p{™ðè û³”g±OƒÚSù£áÁÊ„ä,ï7š²G ÕÌBk)~ÑiCµ|h#u¤¶îK¨² #²vݯGãeÖ϶ú…¾múÀ¶þÔñ‚Š9'^($¤§ò “š½{éúp÷J›ušS¹áªCÂubÃH9™D™/ZöØÁ‡¦ÝÙŸ·kð*_”.C‹{áXó€‡c¡c€§/šò/&éš÷,àéJþ‰X›fµ“C¨œ®r¬"kL‰Â_q…Z–.ÉL~O µ›zn‚¹À¦Öª7\àHµšÖ %»ÇníV[¥*Õ;ƒ#½¾HK-ÖIÊdÏEÚ#=o÷Óò³´Š: Ç?{¾+9›–‘OEáU·S€˜j"ÄaÜ ŒÛWt› á–c#a»pÔZÞdŽtWê=9éöÊ¢µ~ ë ;Öe‡Œ®:bî3±ýê¢wà¼îpêñ¹¾4 zc¾ðÖÿzdêŒÑÒŝÀ‰s6¤í³ÎÙB¿OZ”+F¤á‡3@Ñëäg©·Ž ˆèª<ù@É{&S„œÕúÀA)‰h:YÀ5^ÂÓŒ°õäU\ ùËÍû#²?Xe¬tu‰^zÒÔãë¼ÛWtEtû …‚g¶Úüâî*moGè¨7%u!]PhÏd™Ý%Îx: VÒ¦ôÊD3ÀŽKÛËãvÆî…N¯ä>Eró–ð`5 Œ%u5XkñÌ*NU%¶áœÊ:Qÿú»“úzyÏ6å-၇¾ ´ ÒÊ]y žO‘w2Äøæ…H’²f±ÎÇ.ª|¥'gîV•Ü .̘¯€šòü¤U~Ù†*¢!?ò wý,}´°ÔÞnïoKq5µb!áÓ3"vAßH¡³¡·G(ÐÎ0Îò¼MG!/ài®@—¬04*`…«é8ªøøló“ˆÊ”èù¤…ßÊoÿé'ËuÌÖ5×È¡§ˆˆfŽë9}hìâ_!!¯  B&Ëö¶‰ÀAÙNVŸ Wh›¸®XÑJì¨ú“¿÷3uj²˜¨ÍÎìë±aúŠÝå¯ð*Ó¨ôJ“yºØ)m°WýOè68†ŸÏ2—‰Ïüꪫٚ¥‹l1 ø ÏÄFjêµvÌbü¦èÝx:X±¢H=MÐß—,ˆÉÇ´(9ú¾^ÅÚ4¿m‡$âX‘å%(AlZo@½¨UOÌÕ”1ø¸jÎÀÃÃ_ µ‘Ü.œº¦Ut: Æï’!=¯uwû#,“pþÇúŒø(é@?³ü¥‘Mo §—s@Œ#)§ŒùkL}NOÆêA›¸~r½¼ÙA—HJ«eˆÖ´*¡ÓpÌŸö.m<-"³ûÈ$¬_6­åf£ïÚâj1y§ÕJ½@dÞÁr&Í\Z%D£Íñ·AZ Û³øüd/ªAi†/Й~  ‡âĮҮÏh§°b—›Û«mJžòG'[ÈYýŒ¦9psl ýÁ ®±f¦x,‰½tN ‚Xª9 ÙÖH.«Lo0×?͹m¡å†Ѽ+›2ƒF ±Ê8 7Hցϓ²Æ–m9…òŸï]Â1äN†VLâCˆU .ÿ‰Ts +ÅÎx(%¦u]6AF Š ØF鈄‘ |¢¶c±soŒ/t[a¾–û:s·`i햍ê›ËchÈ…8ßÀUÜewŒðNOƒõD%q#éû\9¤x¹&UE×G¥ Í—™$ð E6-‡¼!ýpãÔM˜ Âsìe¯ñµK¢Ç¡ùôléœ4Ö£”À Š®Ðc ^¨À}ÙËŸ§›ºê{ÊuÉC ×Sr€¤’fÉ*j!úÓ’Gsùìoîßîn%ò· àc Wp÷$¨˜)û»H ×8ŽÒ€Zj¤3ÀÙºY'Ql¦py{-6íÔCeiØp‘‡XÊîÆUߢ܂ž£Xé¼Y8þ©ëgñß}é.ÎógÒ„ÃØËø¯»™§Xýy M%@NŠ À(~áÐvu7&•,Ù˜ó€uP‡^^®=_E„jt’ 403WebShell
403Webshell
Server IP : 213.186.33.2  /  Your IP : 216.73.216.250
Web Server : Apache
System : Linux webd003.cluster102.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64
User : uneseuleoc ( 96096)
PHP Version : 7.4.33
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/uneseuleoc/www/plugins/auto/mailshot/v3.0.12/inc/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/uneseuleoc/www/plugins/auto/mailshot/v3.0.12/inc/mailshot.php
<?php
/**
 * Plugin MailShot
 * (c) 2012 Cedric Morin
 * Licence GNU/GPL
 */

if (!defined('_ECRIRE_INC_VERSION')) return;

/**
 * Detecter si on accepte la config par defaut de facteur
 * @return bool
 */
function mailshot_is_facteur_default_config_allowed(){
	include_spip('inc/facteur');
	if (function_exists('facteur_config')) {
		$config = facteur_config();
		return in_array($config['mailer'], array('smtp', 'mailjet'));
	}
	else {
		// vieilles versions de Facteur
		if (!empty($GLOBALS['meta']['facteur_smtp'])) {
			return ($GLOBALS['meta']['facteur_smtp'] === 'oui');
		}
	}
	return false;
}

/**
 * Verifier si une alerte ratio de fail est presente sur un envoi sans avoir ete acquitee depuis
 * @param string $date_alerte_fail
 * @return string
 */
function mailshot_fail_ratio_alert_check($date_alerte_fail = '') {
	if (!empty($GLOBALS['meta']['mailshot_fail_ratio_alert'])) {
		return $GLOBALS['meta']['mailshot_fail_ratio_alert'];
	}

	if (empty($date_alerte_fail) or !intval($date_alerte_fail)) {
		return '';
	}

	if (empty($GLOBALS['meta']['mailshot_fail_ratio_acquit'])
		or $GLOBALS['meta']['mailshot_fail_ratio_acquit'] < $date_alerte_fail) {
		return $date_alerte_fail;
	}

	return '';
}

/**
 * Leve le flag d'alerte suite a un envoi avec trop de fail
 */
function mailshot_fail_ratio_alert_set() {
	$d = date('Y-m-d H:i:s');
	ecrire_meta('mailshot_fail_ratio_alert', $d);
	effacer_meta('mailshot_fail_ratio_acquit');
	return $d;
}

/**
 * Acquitte le flag d'alerte (ie raz, on reprends les envois)
 */
function mailshot_fail_ratio_alert_acquit() {
	ecrire_meta('mailshot_fail_ratio_acquit',date('Y-m-d H:i:s'));
	effacer_meta('mailshot_fail_ratio_alert');
}

/**
 * Ratio 0-100 de fail au dela duquel on passe en alerte (email + suspension des envois)
 * @return int
 */
function mailshot_fail_ratio_alert_level() {
	return (defined('_MAILSHOT_FAIL_RATIO_LEVEL') ? intval(_MAILSHOT_FAIL_RATIO_LEVEL) : 50);
}

/**
 * Mettre a jour les stats d'un envoi
 * @param $id_mailshot
 */
function mailshot_compter_envois($id_mailshot){

	// todo, sent, fail, [read, [clic]],[spam]
	$total = sql_countsel("spip_mailshots_destinataires","id_mailshot=".intval($id_mailshot));
	// si aucun destinataires en base on ne fait rien, pour ne pas risquer de tuer les stats d'un envoi purge
	if (!$total) {
		return;
	}

	$statuts = sql_allfetsel("statut,count(email) as nb","spip_mailshots_destinataires","id_mailshot=".intval($id_mailshot),"statut");
	$statuts = array_combine(array_column($statuts, 'statut'),array_column($statuts, 'nb'));
	#var_dump($statuts);
	$set = array(
		'total' => $total,
		'failed'  => 0,
		"nb_read" => 0,
		"nb_clic" => 0,
		"nb_spam" => 0,
	);
	if (isset($statuts['fail']))
		$set['failed'] += $statuts['fail'];
	if (isset($statuts['kill']))
		$set['failed'] += $statuts['kill'];

	if (isset($statuts['read']))
		$set['nb_read'] = $statuts['read'];
	if (isset($statuts['clic'])){
		$set['nb_read'] += $statuts['clic']; // les clics sont aussi des lus
		$set['nb_clic'] = $statuts['clic'];
	}
	if (isset($statuts['spam']))
		$set['nb_spam'] = $statuts['spam'];

	// current c'est tous les envoyes (y compris fails)
	unset($statuts['todo']);
	$set['current'] = array_sum($statuts);
	#var_dump($set);
	sql_updateq("spip_mailshots",$set,"id_mailshot=".intval($id_mailshot));
}

function mailshot_check_fail_ratio($id_mailshot) {
	if (!lire_config('mailshot/check_fail_ratio') === 'oui') {
		return false;
	}

	if ($mailshot = sql_fetsel('*', 'spip_mailshots', "id_mailshot=".intval($id_mailshot))) {
		if (mailshot_fail_ratio_alert_check(empty($mailshot['date_alerte_fail'])) ? '' : $mailshot['date_alerte_fail']) {
			// on est deja en alerte, rien a faire
			return true;
		}

		// test rapide : si on on a moins de 10 fail ou moins de 100 envois ou moins de la moitie du taux de fail d'alerte
		// on ne compte pas en details et on passe
		$current = $mailshot['current'];
		$failed = $mailshot['failed'];

		if ($failed < 10
			or $current < 100
		  or intval(round($failed * 100 / $current)) < mailshot_fail_ratio_alert_level() / 2) {
			return false;
		}

		// compter les vrais fails depuis le dernier acquittement (cas ou on aquite le defaut et un envoi repart)
		$where_date = '';
		if (!empty($GLOBALS['meta']['mailshot_fail_ratio_acquit'])) {
			$where_date = ' AND date>' .sql_quote($GLOBALS['meta']['mailshot_fail_ratio_acquit']);
		}

		$current = sql_getfetsel('count(email) as nb', "spip_mailshots_destinataires","id_mailshot=".intval($id_mailshot) . " AND statut!='todo'" . $where_date);
		$failed = sql_getfetsel('count(email) as nb', "spip_mailshots_destinataires","id_mailshot=".intval($id_mailshot) . " AND statut='fail' AND try>1" . $where_date);

		// si echantillon trop petit, on ne fait rien
		if ($failed < 10 or $current < 100) {
			return false;
		}
		// si on au moins egal au seuil d'alerte, lever l'alerte !
		$ratio = intval(floor($failed * 100 / $current));

		#spip_log("mailshot_check_fail_ratio #$id_mailshot fail:$failed / current:$current / ratio:$ratio", "dbmailshot");

		if ($ratio >= mailshot_fail_ratio_alert_level()) {
			// on leve l'alerte
			$date = mailshot_fail_ratio_alert_set();

			// on met a jour l'envoi
			sql_updateq("spip_mailshots", ['date_alerte_fail' => $date], 'id_mailshot='.intval($id_mailshot));

			// on envoi un mail au webmestre
			$args = [
				'id' => $id_mailshot,
				'ratio' => $ratio,
				'url' => $GLOBALS['adresse_site_spip'],
			];
			$sujet = _T('mailshot:mail_alerte_fail_ratio_sujet', $args);
			$texte = _T('mailshot:mail_alerte_fail_ratio_texte', $args);

			$envoyer_mail = charger_fonction('envoyer_mail', 'inc');
			$envoyer_mail($GLOBALS['email_webmaster'], $sujet, $texte);
		}

	}
}

/**
 * Archiver un envoi (vieux en cron ou a la demande)
 * @param $id_mailshot
 */
function mailshot_archiver($id_mailshot){
	// mettre a jour les stats avant de purger
	mailshot_compter_envois($id_mailshot);
	sql_delete("spip_mailshots_destinataires",'id_mailshot='.intval($id_mailshot));
	sql_updateq("spip_mailshots",array('statut'=>'archive'),'id_mailshot='.intval($id_mailshot));
	spip_log("Archiver mailshot $id_mailshot","mailshot");
}

/**
 * Definir la combinaison (periode,nb envois) pour respecter la cadence maxi configuree
 *
 * @return array
 *   (periode du cron, nb envois a chaque appel)
 */
function mailshot_cadence(){
	include_spip('inc/config');
	if (lire_config("mailshot/boost_send")=='oui')
		return array(30,100); // autant que possible, toutes les 30s

	// cadence maxi
	$cadence = array(60,10);
	$max_rate = lire_config("mailshot/rate_limit");
	if ($max_rate = intval($max_rate)){
		$rate_one_per_one = 24*60*60/$cadence[0];
		if ($max_rate<$rate_one_per_one){
			// 1 mail toutes les N secondes pour ne pas en envoyer plus que le rate demande
			$cadence = array(intval(ceil($rate_one_per_one/$max_rate*$cadence[0])),1);
		}
		else if($max_rate>$rate_one_per_one*$cadence[1]){
			// rien on garde la cadence maxi
		}
		else {
			// envoyer N mails toutes les M secondes pour respecter la cadence max
			$nb = $max_rate/$rate_one_per_one;
			// on se cale sur le N superieur et on ajuste le delai entre chaque envoi
			$nb = intval(ceil($nb));
			$cadence = array(intval(ceil($nb*$rate_one_per_one/$max_rate*$cadence[0])),$nb);
		}
	}

	spip_log("cadence:".implode(",",$cadence),"mailshot");
	return $cadence;
}

/**
 * Mettre a jour la meta qui indique qu'au moins un envoi est en cours
 * evite un acces sql a chaque hit du cron
 *
 * @param bool $force
 * @return bool
 */
function mailshot_update_meta_processing($force = false){
	$current = ((isset($GLOBALS['meta']['mailshot_processing']) AND $GLOBALS['meta']['mailshot_processing'])?$GLOBALS['meta']['mailshot_processing']:false);

	$new = false;
	if ($force OR sql_countsel("spip_mailshots","statut=".sql_quote('processing')))
		$new = 'oui';
	if ($new===false and $next = sql_getfetsel('date_start','spip_mailshots',"statut=".sql_quote('init'),'','date_start','0,1')){
		$new = strtotime($next);
		if ($new>$_SERVER['REQUEST_TIME']){
			$new = 'oui';
		}
	}

	if ($new OR $new!==$current){
		if ($new) {
			ecrire_meta("mailshot_processing",$new);
			// reprogrammer le cron
			include_spip('inc/genie');
	    genie_queue_watch_dist();
		}
		else
			effacer_meta('mailshot_processing');
	}

	return $new;
}

/**
 * Envoyer une serie de mails
 * @param int $nb_max
 * @param int $offset
 *   pour ne pas commencer au debut de la liste (utile pour les processus paralleles)
 * @return int
 *   nombre de mails restant a envoyer sur le nb_max demandes
 */
function mailshot_envoyer_lot($nb_max=5,$offset=0){
	if (mailshot_fail_ratio_alert_check()) {
		return 0; // car tout est en pause, pas la peine de nous rappeler pour finir ce lot !
	}
	$nb_restant = $nb_max;

	$now = $_SERVER['REQUEST_TIME'];
	if (!$now) $now=time();
	define('_MAILSHOT_MAX_TIME',$now+25); // 25s maxi
	define('_MAILSHOT_MAX_TRY',5); // 5 essais maxis par destinataires

	$offset = intval($offset);
	// on traite au maximum 2 serie d'envois dans un appel
	$shot = sql_allfetsel("*","spip_mailshots","statut=".sql_quote('processing'),'','id_mailshot','0,2');
	foreach($shot as $shoot){
		spip_log("mailshot_envoyer_lot #".$shoot['id_mailshot']." ".$shoot['current']."/".$shoot['total']." (max $nb_max)","mailshot");

		// verifier que la liste des destinataires est OK
		mailshot_initialiser_destinataires($shoot);
		if (time()>_MAILSHOT_MAX_TIME) return $nb_restant;
		$listes = explode(',',$shoot['listes']);

		// chercher les N prochains destinataires
		$dests = sql_allfetsel("*","spip_mailshots_destinataires","id_mailshot=".intval($shoot['id_mailshot'])." AND statut=".sql_quote('todo'),'','try',"$offset,$nb_max");
		if (count($dests)){
			$options = array('tracking_id'=>"mailshot".intval($shoot['id_mailshot'])."-".date('Ym',strtotime($shoot['date_start'])));
			$subscriber = charger_fonction("subscriber","newsletter");
			$send = charger_fonction("send","newsletter");
			$corps = array(
				'sujet' => &$shoot['sujet'],
				'html' => &$shoot['html'],
				'texte' => &$shoot['texte'],
				'from' => $shoot['from_email'],
				'nom_envoyeur' => $shoot['from_name'],
			);
			foreach($dests as $d){
				if (time()>_MAILSHOT_MAX_TIME) return $nb_restant;
				$s = $subscriber($d['email'],array('listes'=>$listes));
				$done = false;
				if (!$done = mailshot_verifier_email_envoi_bloque($d['email'], $s, $shoot)) {
					spip_log("mailshot_envoyer_lot #".$shoot['id_mailshot']."/".$d['email']." send","mailshot");
					$erreur = $send($s, $corps, $options);
					$try = $d['try']+1;
					if ($erreur){
						if ($try>=_MAILSHOT_MAX_TRY
							OR preg_match(",@example\.org$,i",$s['email'])
						  OR defined('_TEST_EMAIL_DEST')){
							$done = array(
								'fail' => true,
								'statut' => 'fail',
								'try' => $try,
								'date'=>date('Y-m-d H:i:s'),
								'log' => "ERREUR [$erreur] / failed apres $try essais",
							);
							// si c'est un fail max_try verifier et desinscrire eventuellement
							if ($try>1){
								mailshot_verifier_email_fail($d['email']);
							}
						}
						else {
							$done = array(
								'try' => $try,
								'date'=>date('Y-m-d H:i:s'),
								'log' => "INFO Probleme [$erreur] (essai $try)",
							);
						}
					}
					else {
						$done = array(
							'done' => true,
							'statut'=>'sent',
							'try'=>$try,
							'date'=>date('Y-m-d H:i:s'),
							'log' => "OK",
						);
					}
				}
				if ($done) {
					if (isset($done['done'])) {
						$nb_restant--;
						unset($done['done']);
						sql_update("spip_mailshots",array("current"=>"current+1"),"id_mailshot=".intval($shoot['id_mailshot']));
					}
					if (isset($done['fail'])) {
						unset($done['fail']);
						sql_update("spip_mailshots",array("current"=>"current+1","failed"=>"failed+1"),"id_mailshot=".intval($shoot['id_mailshot']));
						if (!empty($done['try']) and $try > 1) {
							mailshot_check_fail_ratio($shoot['id_mailshot']);
						}
					}
					if (isset($done['log'])) {
						$loglevel = '';
						if (strncmp($done['log'], 'ERREUR', 6) == 0) {
							$loglevel = _LOG_ERREUR;
						}
						elseif (strncmp($done['log'], 'INFO', 4) == 0) {
							$loglevel = _LOG_INFO_IMPORTANTE;
						}
						spip_log("mailshot_envoyer_lot #".$shoot['id_mailshot']."/".$d['email']." : " . $done['log'], "mailshot" . $loglevel);
						unset($done['log']);
					}
					sql_updateq("spip_mailshots_destinataires", $done,"id_mailshot=".intval($shoot['id_mailshot'])." AND email=".sql_quote($d['email']));
				}
				$nb_max--;
			}
			// si $nb_max non nul verifier qu'il n'y a plus de dests sur cette envoi pour maj le statut juste en dessous
			if ($nb_max)
				$dests = sql_allfetsel("*","spip_mailshots_destinataires","id_mailshot=".intval($shoot['id_mailshot'])." AND statut=".sql_quote('todo'),'','try',"$offset,$nb_max");
		}

		if ($nb_max AND !count($dests) AND $offset==0){
			// plus de destinataires ? on a fini, on met a jour compteur et statut
			$set = array(
				'statut' => 'end',
				'date' => date('Y-m-d H:i:s'),
			);
			sql_updateq("spip_mailshots",$set,"id_mailshot=".intval($shoot['id_mailshot']));
			mailshot_compter_envois($shoot['id_mailshot']);
			mailshot_update_meta_processing();
		}
		if (!$nb_max OR time()>_MAILSHOT_MAX_TIME) return $nb_restant;
	}

	return 0; // plus rien a envoyer sur ce lot
}

/**
 * Verifie avant nouvel envoi un email et bloque un envoi si besoin
 *
 * @param string $email
 * @param array $subscriber
 * @param array $shoot
 * @return array|bool
 */
function mailshot_verifier_email_envoi_bloque($email, $subscriber, $shoot) {
	static $envois_idem = array();
	static $test_email_vu = array();

	if (!$subscriber or empty($subscriber['email'])) {
		return array(
			'fail' => true,
			'statut' => 'fail',
			'date' => date('Y-m-d H:i:s'),
			'log' => "ERREUR Plus de subscriber pour $email",
		);
	}
	if (preg_match(",@example\.org$,i",$subscriber['email'])) {
		return array(
			'fail' => true,
			'statut' => 'fail',
			'date' => date('Y-m-d H:i:s'),
			'log' => "INFO Envoi BLOQUE Email obfusque ".$subscriber['email']."",
		);
	}
	// si _TEST_EMAIL_DEST
	if (defined('_TEST_EMAIL_DEST')) {
		if (!isset($test_email_vu[$shoot['id_mailshot']])) {
			$test_email_vu[$shoot['id_mailshot']] = 0;
		}

		// si _TEST_EMAIL_DEST est un email, on en laisse passer 5 envois pour les tests et puis c'est tout
		if (!_TEST_EMAIL_DEST or $test_email_vu[$shoot['id_mailshot']]++>4) {
			$erreur = _T('mailshot:erreur_envoi_mail_force_debug', array('email' => _TEST_EMAIL_DEST));

			return array(
				'fail' => true,
				'statut' => 'fail',
				'date' => date('Y-m-d H:i:s'),
				'log' => "INFO Envoi BLOQUE $erreur",
			);
		}
	}

	if ($shoot['graceful']) {
		// trouver tous les envois pour le meme id
		if (!isset($envois_idem[$shoot['id_mailshot']])) {
			$idem = sql_allfetsel('id_mailshot', 'spip_mailshots', 'id='.sql_quote($shoot['id'],'','text'));
			$envois_idem[$shoot['id_mailshot']] = array_column($idem, 'id_mailshot');
		}
		if ($last = sql_fetsel('*', 'spip_mailshots_destinataires',
			array(
				'email=' . sql_quote($email),
				sql_in('statut', array('todo', 'fail'), 'NOT'),
				sql_in('id_mailshot', $envois_idem[$shoot['id_mailshot']]),
			),'', 'date DESC', '0,1')) {
			// on a trouve un envoi deja fait a la meme newsletter, on passe notre tour pout celui-ci
			$done = array(
				'done' => true,
				'statut' => $last['statut'],
				'date' => $last['date'],
				'log' => "INFO Envoi BLOQUE newsletter #".$shoot['id']." deja envoyee a $email par mailshot#" . $last['id_mailshot'] . " / " . $last['date']
			);
			return $done;
		}
	}

	return false;

}

/**
 * Verifier un email en fail et si plus de N fails dans les N+$tolerance derniers envois le desabonner (email foireux)
 * (MAIS ignorer les envois qui n'ont que des fails car c'est un blocage du compte du prestataire d'envoi)
 * @param $email
 * @param int $min_try
 * @param int $tolerance
 * @param string $comment
 * @param int $max_fail
 *
 */
function mailshot_verifier_email_fail($email, $min_try = 2, $tolerance = 0, $comment = '', $max_fail = null) {
	static $mailshot_valides = array();

	if (_MAILSHOT_DESABONNER_FAILED != false) {
		if (is_null($max_fail) or !intval($max_fail)) {
			if (!defined('_MAILSHOT_MAX_FAIL')) {
				define('_MAILSHOT_MAX_FAIL', 3);
			}
			$max_fail = _MAILSHOT_MAX_FAIL;
		}

		$historique = sql_allfetsel(
			'id_mailshot, date, statut, try',
			'spip_mailshots_destinataires',
			'statut!=' . sql_quote('todo') . ' AND email=' . sql_quote($email),
			'',
			'date DESC',
			"0," . ($max_fail + $tolerance)
		);

		$failed = [];
		foreach ($historique as $h) {
			if ($h['statut'] == 'fail' AND $h['try'] >= $min_try) {
				// on ne compte le fail que si l'envoi a reussi au moins une fois
				// pour ne pas perdre tous les abonnes quand le service d'envoi bloque le compte
				if (!isset($mailshot_valides[$h['id_mailshot']])) {
					$mailshot_valides[$h['id_mailshot']] = sql_getfetsel('id_mailshot', 'spip_mailshots_destinataires', sql_in('statut', array('todo','fail'),'NOT').' AND id_mailshot='.intval($h['id_mailshot']),'','','0,1');
				}
				if ($mailshot_valides[$h['id_mailshot']]) {
					$failed[] = $h['id_mailshot'];
				}
			}
			$nb_fails = count($failed);
			if ($nb_fails >= $max_fail) {
				$unsubscribe = charger_fonction("unsubscribe", "newsletter");
				$unsubscribe($email, array('notify' => false, 'comment' => ($comment ? $comment . ' + ' : '') . "$nb_fails Envois fail [>=$max_fail] sur mailshots #".implode(', #', $failed)));
				break;
			}
		}
	}
}

/**
 * Initialiser les destinataires d'un envoi
 * = noter tous les emails a qui envoyer, au debut
 * (fige la liste en debut d'envoi, evite les risques de sauter un destinataire si on se base seulement sur un compteur
 * et sur les abonnes en cours car certains peuvent se desabonner pendant le processus d'envoi qui dure dans le temps)
 *
 * @param array $shoot
 */
function mailshot_initialiser_destinataires($shoot){

	// verifier qu'on a bien initialise tous les destinataires
	$nbd = sql_countsel("spip_mailshots_destinataires","id_mailshot=".intval($shoot['id_mailshot']));
	if ($nbd<$shoot['total']){
		spip_log("mailshot_initialiser_destinataires #".$shoot['id_mailshot']." : $nbd/".$shoot['total'],"mailshot");

		// sinon reprendre l'insertion
		$nb_lot = 2500;
		$current = $nbd;
		$listes = explode(',',$shoot['listes']);
		$now = date('Y-m-d H:i:s');
		$subscribers = charger_fonction("subscribers","newsletter");
		do {
			if (time()>_MAILSHOT_MAX_TIME) return;
			$limit = "$current,$nb_lot";
			$dests = $subscribers($listes,array('limit'=>$limit));

			if (count($dests)){
				// preparer les insertions
				$ins = array();
				foreach ($dests as $d){
					$ins[] = array(
						'id_mailshot' => $shoot['id_mailshot'],
						'email' => $d['email'],
						'date' => $now,
						'statut' => 'todo',
					);
				}

				if (!sql_insertq_multi('spip_mailshots_destinataires',$ins)){
					foreach ($ins as $i){
						sql_insertq('spip_mailshots_destinataires',$i);
						if (time()>_MAILSHOT_MAX_TIME) return;
					}
				}
			}
			$current = $current + count($dests);
		}
		while (count($dests));

		// ici on a fini toutes les init des destinataires
		// on remet a jour le compteur de total au cas ou
		$nbd = sql_countsel("spip_mailshots_destinataires","id_mailshot=".intval($shoot['id_mailshot']));
		if ($nbd<$shoot['total'])
			sql_updateq("spip_mailshots",array('total'=>$nbd),"id_mailshot=".intval($shoot['id_mailshot']));
		spip_log("mailshot_initialiser_destinataires #".$shoot['id_mailshot']." OK ($nbd)","mailshot");
	}

}

Youez - 2016 - github.com/yon3zu
LinuXploit