ÿØÿà JFIF    ÿÛ „  ( %"1!%)+...383,7(-.+  -+++--++++---+-+-----+---------------+---+-++7-----ÿÀ  ß â" ÿÄ     ÿÄ H    !1AQaq"‘¡2B±ÁÑð#R“Ò Tbr‚²á3csƒ’ÂñDS¢³$CÿÄ   ÿÄ %  !1AQa"23‘ÿÚ   ? ôÿ ¨pŸªáÿ —åYõõ\?àÒü©ŠÄï¨pŸªáÿ —åYõõ\?àÓü©ŠÄá 0Ÿªáÿ Ÿå[úƒ ú®ði~TÁbqÐ8OÕpÿ ƒOò¤Oè`–RÂáœá™êi€ßÉ< FtŸI“öÌ8úDf´°å}“¾œ6  öFá°y¥jñÇh†ˆ¢ã/ÃÐ:ªcÈ "Y¡ðÑl>ÿ ”ÏËte:qž\oäŠe÷󲍷˜HT4&ÿ ÓÐü6ö®¿øþßèô Ÿ•7Ñi’•j|“ñì>b…þS?*Óôÿ ÓÐü*h¥£ír¶ü UãS炟[AÐaè[ûª•õ&õj?†Éö+EzP—WeÒírJFt ‘BŒ†Ï‡%#tE Øz ¥OÛ«!1›üä±Í™%ºÍãö]°î(–:@<‹ŒÊö×òÆt¦ãº+‡¦%ÌÁ²h´OƒJŒtMÜ>ÀÜÊw3Y´•牋4ǍýʏTì>œú=Íwhyë,¾Ôò×õ¿ßÊa»«þˆѪQ|%6ž™A õ%:øj<>É—ÿ Å_ˆCbõ¥š±ý¯Ýƒï…¶|RëócÍf溪“t.СøTÿ *Ä¿-{†çàczůŽ_–^XþŒ±miB[X±d 1,é”zEù»& î9gœf™9Ð'.;—™i}!ôšåîqêÛ٤ёý£½ÆA–àôe"A$˝Úsäÿ ÷Û #°xŸëí(l »ý3—¥5m! rt`†0~'j2(]S¦¦kv,ÚÇ l¦øJA£Šƒ J3E8ÙiŽ:cÉžúeZ°€¯\®kÖ(79«Ž:¯X”¾³Š&¡* ….‰Ž(ÜíŸ2¥ª‡×Hi²TF¤ò[¨íÈRëÉ䢍mgÑ.Ÿ<öäS0í„ǹÁU´f#Vß;Õ–…P@3ío<ä-±»Ž.L|kªÀê›fÂ6@»eu‚|ÓaÞÆŸ…¨ááå>åŠ?cKü6ùTÍÆ”†sĤÚ;H2RÚ†õ\Ö·Ÿn'¾ ñ#ºI¤Å´%çÁ­‚â7›‹qT3Iï¨ÖÚ5I7Ë!ÅOóŸ¶øÝñØôת¦$Tcö‘[«Ö³šÒ';Aþ ¸èíg A2Z"i¸vdÄ÷.iõ®§)¿]¤À†–‡É&ä{V¶iŽ”.Ó×Õÿ û?h¬Mt–íª[ÿ Ñÿ ÌV(í}=ibÔ¡›¥¢±b Lô¥‡piη_Z<‡z§èŒ)iÖwiÇ 2hÙ3·=’d÷8éŽ1¦¸c¤µ€7›7Ø ð\á)} ¹fËí›pAÃL%âc2 í§æQz¿;T8sæ°qø)QFMð‰XŒÂ±N¢aF¨…8¯!U  Z©RÊ ÖPVÄÀÍin™Ì-GˆªÅËŠ›•zË}º±ŽÍFò¹}Uw×#ä5B¤{î}Ð<ÙD é©¤&‡ïDbàÁôMÁ." ¤‡ú*õ'VŽ|¼´Úgllº¼klz[Æüï÷Aób‡Eÿ dÑ»Xx9ÃÜ£ÁT/`¼¸vI±Ýµ·Ë‚“G³þ*Ÿû´r|*}<¨îºœ @¦mÄ’M¹”.œ«Y–|6ÏU¤jç¥ÕÞqO ˜kDÆÁ¨5ÿ š;ÐЦ¦€GÙk \ –Þ=â¼=SͧµªS°ÚÍpÜãQűÀõ¬?ÃÁ1Ñ•õZà?hóœ€ L¦l{Y*K˜Ù›zc˜–ˆâ ø+¾ ­-Ök¥%ùEÜA'}ˆ><ÊIè“bpÍ/qÞâvoX€w,\úªò6Z[XdÒæ­@Ö—€$òJí#é>'°Ú ôª˜<)4ryÙ£|óAÅn5žêŸyÒäMÝ2{"}‰–¤l÷ûWX\l¾Á¸góÉOÔ /óñB¤f¸çñ[.P˜ZsÊË*ßT܈§QN¢’¡¨§V¼(Üù*eÕ“”5T¨‹Âê¥FŒã½Dü[8'Ò¥a…Ú¶k7a *•›¼'Ò·\8¨ª\@\õ¢¦íq+DÙrmÎ…_ªæ»ŠÓœ¡¯’Ré9MÅ×D™lælffc+ŒÑ,ý™ÿ ¯þǤ=Å’Á7µ÷ÚÛ/“Ü€ñýã¼àí¾ÕÑ+ƒ,uµMâÀÄbm:ÒÎPæ{˜Gz[ƒ¯«® KHà`ߨŠéí¯P8Aq.C‰ à€kòpj´kN¶qô€…Õ,ÜNŠª-­{Zö’æû44‰sŽè‰îVíRœÕm" 6?³D9¡ÇTíÅꋇ`4«¸ÝÁô ï’ýorqКÇZ«x4Žâéþuïf¹µö[P ,Q£éaX±`PÉÍZ ¸äYúg üAx ’6Lê‚xÝÓ*äQ  Ï’¨hÍ =²,6ï#rÃ<¯–£»ƒ‹,–ê•€ aÛsñ'%Æ"®ÛüìBᝠHÚ3ß°©$“XnœÖ’î2ËTeûìxîß ¦å¿çÉ ðK§þ{‘t‚Ϋ¬jéîZ[ ”š7L¥4VÚCE×]m¤Øy”ä4-dz£œ§¸x.*ãÊÊ b÷•h:©‡¦s`BTÁRû¾g⻩‹jø sF¢àJøFl‘È•Xᓁà~*j¯ +(ÚÕ6-£¯÷GŠØy‚<Ç’.F‹Hœw(+)ÜÜâÈzÄäT§FߘãÏ;DmVœ3Àu@mÚüXÝü•3B¨òÌÁÛ<·ÃÜ z,Ì@õÅ·d2]ü8s÷IôÞ¯^Ç9¢u„~ëAŸï4«M? K]­ÅàPl@s_ p:°¬ZR”´›JC[CS.h‹ƒïËœ«Æ]–÷ó‚wR×k7X‰k›‘´ù¦=¡«‰¨¨Â')—71ó’c‡Ðúµ `é.{§p¹ój\Ž{1h{o±Ý=áUÊïGÖŒõ–-BÄm+AZX¶¡ ïHðæ¥JmÙ;…䡟ˆ¦ ° äšiÉg«$üMk5¤L“’çÊvïâï ,=f“"íἊ5ô¬x6{ɏžID0e¸vçmi'︧ºð9$ò¹÷*£’9ÿ ²TÔ…×>JV¥}Œ}$p[bÔ®*[jzS*8 ”·T›Í–ñUîƒwo$áè=LT™ç—~ô·¤ÈÚ$榍q‰„+´kFm)ž‹©i–ËqÞŠ‰à¶ü( ‚•§ •°ò·‡#5ª•µÊ﯅¡X¨šÁ*F#TXJÊ ušJVÍ&=iÄs1‚3•'fý§5Ñ<=[íÞ­ PÚ;ѱÌ_~Ä££8rÞ ²w;’hDT°>ÈG¬8Á²ÚzŽ®ò®qZcqJêäÞ-ö[ܘbň±çb“ж31²n×iƒðÕ;1¶þÉ ªX‰,ßqÏ$>•î íZ¥Z 1{ç൵+ƒÕµ¥°T$§K]á»Ûï*·¤tMI’ÂZbŽÕiÒ˜}bÓ0£ª5›¨ [5Ž^ÝœWøÂÝh° ¢OWun£¤5 a2Z.G2³YL]jåtì”ä ÁÓ‘%"©<Ôúʰsº UZvä‡ÄiÆÒM .÷V·™ø#kèýiíÌ–ª)µT[)BˆõÑ xB¾B€ÖT¨.¥~ð@VĶr#¸ü*åZNDŽH;âi ],©£öØpù(šºãö¼T.uCê•4@ÿ GÕÛ)Cx›®0ø#:ÏðFÒbR\(€€Ä®fã4Þ‰Fä¯HXƒÅ,†öEÑÔÜ]Öv²?tLÃvBY£ú6Êu5ÅAQ³1‘’¬x–HŒÐ‡ ^ ¸KwJôÖŽ5×CÚ¨vÜ«/B0$×k°=ðbÇ(Ï)w±A†Á† 11Í=èQšµ626ŒÜ/`G«µ<}—-Ö7KEHÈÉðóȤmݱû±·ø«Snmá=“䫚mݱŸ¡¶~ó·“äUóJæúòB|E LêŽy´jDÔ$G¢þÐñ7óR8ýÒ…Ç› WVe#·Ÿ p·Fx~•ݤF÷0Èÿ K¯æS<6’¡WШ; ´ÿ ¥Êø\Òuî†åÝ–VNœkÒ7oòX¨Á­Ø÷FÎÑä±g÷ÿ M~Çî=p,X´ ÝÌÚÅ‹’ÃjÖ.ØöÏñ qïQ¤ÓZE†° =6·]܈ s¸>v•Ž^Ý\wq9r‰Î\¸¡kURÒ$­*‹Nq?Þª*!sŠÆ:TU_u±T+øX¡ ®¹¡,ÄâÃBTsÜ$Ø›4m椴zÜK]’’›Pƒ @€#â˜`é¹=I‡fiV•Ôî“nRm+µFPOhÍ0B£ €+¬5c v•:P'ÒyÎ ‰V~‚Ó†ÖuókDoh$å\*ö%Ю=£«…aȼ½÷Û.-½VŒŠ¼'lyî±1¬3ó#ÞE¿ÔS¤gV£m›=§\û"—WU¤ÚǼÿ ÂnÁGŒÃ ‚õN D³õNÚíŒÕ;HôyÄÈ©P¹Ä{:?R‘Ô¨âF÷ø£bÅó® JS|‚R÷ivýáâ€Æé¡è³´IئÑT!§˜•ت‚¬â@q€wnïCWÄ@JU€ê¯m6]Ï:£âx'+ÒðXvÓ¦Úm=–´7œ $ì“B£~p%ÕŸUþ« N@¼üï~w˜ñø5®—'Ôe»¤5ã//€ž~‰Tþ›Å7•#¤× Íö pÄ$ùeåì*«ÓŠEØWEÈsßg ¦ûvžSsLpºÊW–âµEWöˬH; ™!CYõZ ÃÄf æ#1W. \uWâ\,\Çf j’<qTbên›Î[vxx£ë 'ö¨1›˜ÀM¼Pÿ H)ƒêêŒA7s,|F“ 꺸k³9Ìö*ç®;Ö!Ö$Eiž•¹ÒÚ†ýóéÝû¾ÕS®ó$’NÝäŸz¤5r¦ãÄÃD÷Üø!°ø‡Ô&@m™Ì^Ãä­d q5Lnÿ N;.6½·N|#ä"1Nƒx“ã<3('&ñßt  ~ªu”1Tb㫨9ê–›–bìd$ߣ=#ÕãÒmU¯eí$EFù5ýYô櫨æì™Ç—±ssM]·á¿0ÕåJRÓªîiƒ+O58ÖñªŠÒx" \µâá¨i’¤i —Ö ” M+M¤ë9‚‰A¦°Qõ¾ßøK~¼Ã‘g…Ö´~÷Ï[3GUœÒ½#…kàÔ®Ò”‰³·dWV‰IP‰Ú8u¹”E ÖqLj¾êÕCBš{A^Âß;–¨`¯¬ìö ˼ ×tìø.tƐm*n¨y4o&Àx¥n¦×î‡aupáÛj8¿m›è¶ã!o½;ß0y^ý×^EÑ¿ÒjzŒ­)vÚÑnÄL …^ªô× ‡—‚3k Îý­hï]içå–îÏ*÷ñþ»Ô CÒjøjÍznˆ´ ¹#b'Fô‹ ‰v¥'’à'T´ƒHýÍ%M‰ ƒ&ÆÇŒï1 ‘ –Þ ‰i¬s žR-Ÿ kЬá¬7:þ 0ŒÅÒÕ/aÙ¬ÃÝ#Úøœ ©aiVc‰. ¹¦ãµ” ›Yg¦›ÆÎýº°f³7ƒhá·¸­}&D9¡ÂsÉÙÞèŠõØàC™¨ñbFC|´Ü(ŸƒÚÒ-%»'a Ì¿)ËÇn¿úÿ ÞŽX…4ÊÅH^ôΑí@ù¹Eh¶“L8Çjù ¼ÎåVªóR©Ï5uà V4lZß®=€xÖŸ–ÑÈ ÷”¨°¾__yM1tÉ?uÆþIkÄgæ@þ[¢†°XÃJ£j·:nkÅ¢u ‘}âGzö­/IµèЬ¼48q¦F°ŽR¼=ûì{´¯RýicS ÕÛ íNtÍÙï£,w4rêì®»~x(©Uñ§#Ñ&œÕ¤>ÎåÍÓ9’Ö{9eV­[Öjâ²ãu]˜å2›qÑšÕJç0€sÄ|Êëè0튔bÁ>“{×_F`Ø©ºê:µä,v¤ðfc1±"«ÔÍän1#=· Âøv~H½ÐßA¾¿Ü€Óš]Õ; I¾÷ç‚Qi†î¹9ywÔKG˜áñ zQY—§ÃÕZ07§X‚ Áh;ÁM)iÌCH-¯T‘ë|A0{Ò½LÚ–TâÖkÜ’dÀ“rmm»”جPF³ÖcbE§T€ÒxKºû’Ó®7±²(\4ŽÃ¸Uu@j™yĵ;³µ!Á¢b.W¤=mõ´êµK k ¸K^ÜÛ#p*Ü14qkZç5ïë †°5Ï%ÍÛ<Õ¤×Ô¥ê†C Õ´¼ú$ƒÖ“”]Ù¬qÞÚ[4©ý!ûÏ—Áb쳐XµA¬â~`›Çr¸8ìùÝ䫦<>ä÷«?xs´ÇÑ /á;¹øüÊÈÙà{"@Žïzâ¬[âß‚ U_<ÇŸ½4èN˜ú61®qŠu ¦þF£»äJ_ˆÙÎ~ ÞAã–݄ϗrŠD;xTž‘ô`É«…suãO`?³à™ô Lý#Íc5öoæØ‚y´´÷«ZR§<&JÇ+éâô´€i!Àˆ0æAoàðLèÖ-2ŸõW.’t^–(KÁmHµV@xÜÇy®Ñø­â^:Ú3w· 7½¹°ñ¸â¹®:',«Mœ—n­Á+Ãbš LÈ‘ÄnRÓÅœ%¦²‰¨ùQ:¤f‚ "PÕtô¸…cæl…&˜Ú˜Ôkv‹ž+vŠ,=¢v­6—Xy*¥t£«<™:“aîϲ=¦6rO]XI¿Œ÷¤zÚ­›¶ 6÷”w\d ü~v®ˆÌk«^m<ÿ ¢‰Õ\)ùºŽ;… lîÙÅEŠ®cѾ@vnMÏ,¼“ñ•ŽBxðÃzãÇç%3ˆ"}Ù•Åî> BÉú;Ò]V+P˜F_´ßé> Øše|ï‡ÄOmFæÇ ãqÞ$/xÐx­z`ï9"œÜij‚!7.\Td…9M‡•iŽ‹¾‘50ÞŽn¥ß4ÉôO ¹*í^QêËÜÇÌ8=ާs‰'ÂëÙ«á%Pú[O †ÅP¯Vsް.‰,kc¶ ¬A9n˜XÎ-ÞšN["¹QÕ‰ƒMýÁߺXJæÍaLj¾×Ãmã¾ãÚ uñÒþåQô¦¥ /ÄUx:‚ÍÜ’ Đ©ØÝ3V¨‰ÕnÐ6ó*óúK­«…c ¯U òhsý­jóÔj#,ímŒRµ«lbïUTŒÑ8†Ä0œÏr`ð¡¬É Ї ë"À² ™ 6¥ f¶ ¢ÚoܱԷ-<Àî)†a¶ž'Ú»¨TXqØæ¶÷YÄHy˜9ÈIW­YÀuMFë ºÏ’AqÌ4·/Ú †ô'i$øä­=Ä Ý|öK×40è|È6p‘0§)o¥ctî§H+CA-“ xØ|ÐXАç l8íºð3Ø:³¤¬KX¯UÿÙ setLanguage('en_gb', __DIR__ . '/language/'); // Configure a callback function to handle errors when $this->edebug() is called $this->Debugoutput = function ($message, $level) { Log::add(sprintf('Error in Mail API: %s', $message), Log::ERROR, 'mail'); }; // If debug mode is enabled then set SMTPDebug to the maximum level if (defined('JDEBUG') && JDEBUG) { $this->SMTPDebug = 4; } // Don't disclose the PHPMailer version $this->XMailer = ' '; } /** * Returns the global email object, only creating it if it doesn't already exist. * * NOTE: If you need an instance to use that does not have the global configuration * values, use an id string that is not 'Joomla'. * * @param string $id The id string for the Mail instance [optional] * @param boolean $exceptions Flag if Exceptions should be thrown [optional] * * @return Mail The global Mail object * * @since 11.1 */ public static function getInstance($id = 'Joomla', $exceptions = true) { if (empty(self::$instances[$id])) { self::$instances[$id] = new Mail($exceptions); } return self::$instances[$id]; } /** * Send the mail * * @return boolean|\JException Boolean true if successful, boolean false if the `mailonline` configuration is set to 0, * or a JException object if the mail function does not exist or sending the message fails. * * @since 11.1 * @throws \RuntimeException */ public function Send() { if (Factory::getConfig()->get('mailonline', 1)) { if (($this->Mailer == 'mail') && !function_exists('mail')) { return \JError::raiseNotice(500, \JText::_('JLIB_MAIL_FUNCTION_DISABLED')); } try { // Try sending with default settings $result = parent::send(); } catch (\phpmailerException $e) { $result = false; if ($this->SMTPAutoTLS) { /** * PHPMailer has an issue with servers with invalid certificates * * See: https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting#opportunistic-tls */ $this->SMTPAutoTLS = false; try { // Try it again with TLS turned off $result = parent::send(); } catch (\phpmailerException $e) { // Keep false for B/C compatibility $result = false; } } } if ($result == false) { $result = \JError::raiseNotice(500, \JText::_($this->ErrorInfo)); } return $result; } Factory::getApplication()->enqueueMessage(\JText::_('JLIB_MAIL_FUNCTION_OFFLINE')); return false; } /** * Set the From and FromName properties. * * @param string $address The sender email address * @param string $name The sender name * @param boolean $auto Whether to also set the Sender address, defaults to true * * @return boolean * * @since 11.1 */ public function setFrom($address, $name = '', $auto = true) { try { if (parent::setFrom($address, $name, $auto) === false) { return false; } } catch (\phpmailerException $e) { // The parent method will have already called the logging callback, just log our deprecated error handling message Log::add(__METHOD__ . '() will not catch phpmailerException objects as of 4.0.', Log::WARNING, 'deprecated'); return false; } } /** * Set the email sender * * @param mixed $from email address and Name of sender * array([0] => email Address, [1] => Name) * or as a string * * @return Mail|boolean Returns this object for chaining on success or boolean false on failure. * * @since 11.1 * @throws \UnexpectedValueException */ public function setSender($from) { // Wrapped in try/catch if PHPMailer is configured to throw exceptions try { if (is_array($from)) { // If $from is an array we assume it has an address and a name if (isset($from[2])) { // If it is an array with entries, use them $result = $this->setFrom(MailHelper::cleanLine($from[0]), MailHelper::cleanLine($from[1]), (bool) $from[2]); } else { $result = $this->setFrom(MailHelper::cleanLine($from[0]), MailHelper::cleanLine($from[1])); } } elseif (is_string($from)) { // If it is a string we assume it is just the address $result = $this->setFrom(MailHelper::cleanLine($from)); } else { // If it is neither, we log a message and throw an exception Log::add(\JText::sprintf('JLIB_MAIL_INVALID_EMAIL_SENDER', $from), Log::WARNING, 'jerror'); throw new \UnexpectedValueException(sprintf('Invalid email Sender: %s, Mail::setSender(%s)', $from)); } // Check for boolean false return if exception handling is disabled if ($result === false) { return false; } } catch (\phpmailerException $e) { // The parent method will have already called the logging callback, just log our deprecated error handling message Log::add(__METHOD__ . '() will not catch phpmailerException objects as of 4.0.', Log::WARNING, 'deprecated'); return false; } return $this; } /** * Set the email subject * * @param string $subject Subject of the email * * @return Mail Returns this object for chaining. * * @since 11.1 */ public function setSubject($subject) { $this->Subject = MailHelper::cleanLine($subject); return $this; } /** * Set the email body * * @param string $content Body of the email * * @return Mail Returns this object for chaining. * * @since 11.1 */ public function setBody($content) { /* * Filter the Body * TODO: Check for XSS */ $this->Body = MailHelper::cleanText($content); return $this; } /** * Add recipients to the email. * * @param mixed $recipient Either a string or array of strings [email address(es)] * @param mixed $name Either a string or array of strings [name(s)] * @param string $method The parent method's name. * * @return Mail|boolean Returns this object for chaining on success or boolean false on failure. * * @since 11.1 * @throws \InvalidArgumentException */ protected function add($recipient, $name = '', $method = 'addAddress') { $method = lcfirst($method); // If the recipient is an array, add each recipient... otherwise just add the one if (is_array($recipient)) { if (is_array($name)) { $combined = array_combine($recipient, $name); if ($combined === false) { throw new \InvalidArgumentException("The number of elements for each array isn't equal."); } foreach ($combined as $recipientEmail => $recipientName) { $recipientEmail = MailHelper::cleanLine($recipientEmail); $recipientName = MailHelper::cleanLine($recipientName); // Wrapped in try/catch if PHPMailer is configured to throw exceptions try { // Check for boolean false return if exception handling is disabled if (call_user_func('parent::' . $method, $recipientEmail, $recipientName) === false) { return false; } } catch (\phpmailerException $e) { // The parent method will have already called the logging callback, just log our deprecated error handling message Log::add(__METHOD__ . '() will not catch phpmailerException objects as of 4.0.', Log::WARNING, 'deprecated'); return false; } } } else { $name = MailHelper::cleanLine($name); foreach ($recipient as $to) { $to = MailHelper::cleanLine($to); // Wrapped in try/catch if PHPMailer is configured to throw exceptions try { // Check for boolean false return if exception handling is disabled if (call_user_func('parent::' . $method, $to, $name) === false) { return false; } } catch (\phpmailerException $e) { // The parent method will have already called the logging callback, just log our deprecated error handling message Log::add(__METHOD__ . '() will not catch phpmailerException objects as of 4.0.', Log::WARNING, 'deprecated'); return false; } } } } else { $recipient = MailHelper::cleanLine($recipient); // Wrapped in try/catch if PHPMailer is configured to throw exceptions try { // Check for boolean false return if exception handling is disabled if (call_user_func('parent::' . $method, $recipient, $name) === false) { return false; } } catch (\phpmailerException $e) { // The parent method will have already called the logging callback, just log our deprecated error handling message Log::add(__METHOD__ . '() will not catch phpmailerException objects as of 4.0.', Log::WARNING, 'deprecated'); return false; } } return $this; } /** * Add recipients to the email * * @param mixed $recipient Either a string or array of strings [email address(es)] * @param mixed $name Either a string or array of strings [name(s)] * * @return Mail|boolean Returns this object for chaining. * * @since 11.1 */ public function addRecipient($recipient, $name = '') { return $this->add($recipient, $name, 'addAddress'); } /** * Add carbon copy recipients to the email * * @param mixed $cc Either a string or array of strings [email address(es)] * @param mixed $name Either a string or array of strings [name(s)] * * @return Mail|boolean Returns this object for chaining on success or boolean false on failure. * * @since 11.1 */ public function addCc($cc, $name = '') { // If the carbon copy recipient is an array, add each recipient... otherwise just add the one if (isset($cc)) { return $this->add($cc, $name, 'addCC'); } return $this; } /** * Add blind carbon copy recipients to the email * * @param mixed $bcc Either a string or array of strings [email address(es)] * @param mixed $name Either a string or array of strings [name(s)] * * @return Mail|boolean Returns this object for chaining on success or boolean false on failure. * * @since 11.1 */ public function addBcc($bcc, $name = '') { // If the blind carbon copy recipient is an array, add each recipient... otherwise just add the one if (isset($bcc)) { return $this->add($bcc, $name, 'addBCC'); } return $this; } /** * Add file attachment to the email * * @param mixed $path Either a string or array of strings [filenames] * @param mixed $name Either a string or array of strings [names] * @param mixed $encoding The encoding of the attachment * @param mixed $type The mime type * @param string $disposition The disposition of the attachment * * @return Mail|boolean Returns this object for chaining on success or boolean false on failure. * * @since 12.2 * @throws \InvalidArgumentException */ public function addAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream', $disposition = 'attachment') { // If the file attachments is an array, add each file... otherwise just add the one if (isset($path)) { // Wrapped in try/catch if PHPMailer is configured to throw exceptions try { $result = true; if (is_array($path)) { if (!empty($name) && count($path) != count($name)) { throw new \InvalidArgumentException('The number of attachments must be equal with the number of name'); } foreach ($path as $key => $file) { if (!empty($name)) { $result = parent::addAttachment($file, $name[$key], $encoding, $type, $disposition); } else { $result = parent::addAttachment($file, $name, $encoding, $type, $disposition); } } } else { $result = parent::addAttachment($path, $name, $encoding, $type, $disposition); } // Check for boolean false return if exception handling is disabled if ($result === false) { return false; } } catch (\phpmailerException $e) { // The parent method will have already called the logging callback, just log our deprecated error handling message Log::add(__METHOD__ . '() will not catch phpmailerException objects as of 4.0.', Log::WARNING, 'deprecated'); return false; } } return $this; } /** * Unset all file attachments from the email * * @return Mail Returns this object for chaining. * * @since 12.2 */ public function clearAttachments() { parent::clearAttachments(); return $this; } /** * Unset file attachments specified by array index. * * @param integer $index The numerical index of the attachment to remove * * @return Mail Returns this object for chaining. * * @since 12.2 */ public function removeAttachment($index = 0) { if (isset($this->attachment[$index])) { unset($this->attachment[$index]); } return $this; } /** * Add Reply to email address(es) to the email * * @param mixed $replyto Either a string or array of strings [email address(es)] * @param mixed $name Either a string or array of strings [name(s)] * * @return Mail|boolean Returns this object for chaining on success or boolean false on failure. * * @since 11.1 */ public function addReplyTo($replyto, $name = '') { return $this->add($replyto, $name, 'addReplyTo'); } /** * Sets message type to HTML * * @param boolean $ishtml Boolean true or false. * * @return Mail Returns this object for chaining. * * @since 12.3 */ public function isHtml($ishtml = true) { parent::isHTML($ishtml); return $this; } /** * Send messages using $Sendmail. * * This overrides the parent class to remove the restriction on the executable's name containing the word "sendmail" * * @return void * * @since 11.1 */ public function isSendmail() { // Prefer the Joomla configured sendmail path and default to the configured PHP path otherwise $sendmail = Factory::getConfig()->get('sendmail', ini_get('sendmail_path')); // And if we still don't have a path, then use the system default for Linux if (empty($sendmail)) { $sendmail = '/usr/sbin/sendmail'; } $this->Sendmail = $sendmail; $this->Mailer = 'sendmail'; } /** * Use sendmail for sending the email * * @param string $sendmail Path to sendmail [optional] * * @return boolean True on success * * @since 11.1 */ public function useSendmail($sendmail = null) { $this->Sendmail = $sendmail; if (!empty($this->Sendmail)) { $this->isSendmail(); return true; } else { $this->isMail(); return false; } } /** * Use SMTP for sending the email * * @param string $auth SMTP Authentication [optional] * @param string $host SMTP Host [optional] * @param string $user SMTP Username [optional] * @param string $pass SMTP Password [optional] * @param string $secure Use secure methods * @param integer $port The SMTP port * * @return boolean True on success * * @since 11.1 */ public function useSmtp($auth = null, $host = null, $user = null, $pass = null, $secure = null, $port = 25) { $this->SMTPAuth = $auth; $this->Host = $host; $this->Username = $user; $this->Password = $pass; $this->Port = $port; if ($secure == 'ssl' || $secure == 'tls') { $this->SMTPSecure = $secure; } if (($this->SMTPAuth !== null && $this->Host !== null && $this->Username !== null && $this->Password !== null) || ($this->SMTPAuth === null && $this->Host !== null)) { $this->isSMTP(); return true; } else { $this->isMail(); return false; } } /** * Function to send an email * * @param string $from From email address * @param string $fromName From name * @param mixed $recipient Recipient email address(es) * @param string $subject email subject * @param string $body Message body * @param boolean $mode false = plain text, true = HTML * @param mixed $cc CC email address(es) * @param mixed $bcc BCC email address(es) * @param mixed $attachment Attachment file name(s) * @param mixed $replyTo Reply to email address(es) * @param mixed $replyToName Reply to name(s) * * @return boolean True on success * * @since 11.1 */ public function sendMail($from, $fromName, $recipient, $subject, $body, $mode = false, $cc = null, $bcc = null, $attachment = null, $replyTo = null, $replyToName = null) { // Create config object $config = Factory::getConfig(); $this->setSubject($subject); $this->setBody($body); // Are we sending the email as HTML? $this->isHtml($mode); /* * Do not send the message if adding any of the below items fails */ if ($this->addRecipient($recipient) === false) { return false; } if ($this->addCc($cc) === false) { return false; } if ($this->addBcc($bcc) === false) { return false; } if ($this->addAttachment($attachment) === false) { return false; } // Take care of reply email addresses if (is_array($replyTo)) { $numReplyTo = count($replyTo); for ($i = 0; $i < $numReplyTo; $i++) { if ($this->addReplyTo($replyTo[$i], $replyToName[$i]) === false) { return false; } } } elseif (isset($replyTo)) { if ($this->addReplyTo($replyTo, $replyToName) === false) { return false; } } elseif ($config->get('replyto')) { $this->addReplyTo($config->get('replyto'), $config->get('replytoname')); } // Add sender to replyTo only if no replyTo received $autoReplyTo = (empty($this->ReplyTo)) ? true : false; if ($this->setSender(array($from, $fromName, $autoReplyTo)) === false) { return false; } return $this->Send(); } /** * Sends mail to administrator for approval of a user submission * * @param string $adminName Name of administrator * @param string $adminEmail Email address of administrator * @param string $email [NOT USED TODO: Deprecate?] * @param string $type Type of item to approve * @param string $title Title of item to approve * @param string $author Author of item to approve * @param string $url A URL to included in the mail * * @return boolean True on success * * @since 11.1 * @deprecated 4.0 Without replacement please implement it in your own code */ public function sendAdminMail($adminName, $adminEmail, $email, $type, $title, $author, $url = null) { $subject = \JText::sprintf('JLIB_MAIL_USER_SUBMITTED', $type); $message = sprintf(\JText::_('JLIB_MAIL_MSG_ADMIN'), $adminName, $type, $title, $author, $url, $url, 'administrator', $type); $message .= \JText::_('JLIB_MAIL_MSG') . "\n"; if ($this->addRecipient($adminEmail) === false) { return false; } $this->setSubject($subject); $this->setBody($message); return $this->Send(); } }