PageRenderTime 45ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/controllers/components/qdmail.php

http://github.com/slywalker/account_manager
PHP | 4121 lines | 3564 code | 216 blank | 341 comment | 530 complexity | c33ac2b2c158532df01d2aa103a6cf7b MD5 | raw file
Possible License(s): MIT
  1. <?php
  2. /**
  3. * Qdmail ver 1.2.6b
  4. * E-Mail for multibyte charset
  5. *
  6. * PHP versions 4 and 5 (PHP4.3 upper)
  7. *
  8. * Copyright 2008, Spok in japan , tokyo
  9. * hal456.net/qdmail : http://hal456.net/qdmail/
  10. * & CPA-LAB/Technical : http://www.cpa-lab.com/tech/
  11. * Licensed under The MIT License License
  12. *
  13. * @copyright Copyright 2008, Spok.
  14. * @link http://hal456.net/qdmail/
  15. * @version 1.2.6b
  16. * @lastmodified 2008-10-23
  17. * @license http://www.opensource.org/licenses/mit-license.php The MIT License
  18. *
  19. * Qdmail is sending e-mail library for multibyte language ,
  20. * easy , quickly , usefull , and you can specify deeply the details.
  21. * Copyright (C) 2008 spok
  22. */
  23. //-------------------------------------------
  24. // For CakePHP , extended 'Object' Class ,
  25. // if including in CakePHP Component .
  26. // At normal PHP Script or another Framework ,
  27. // 'QdmailBranch' means Dummy Base Class .
  28. //-------------------------------------------
  29. if (!defined('QD_DS')) {
  30. define('QD_DS', DIRECTORY_SEPARATOR);
  31. }
  32. if ( defined('CAKE_CORE_INCLUDE_PATH') || defined('CAKE')) {
  33. class QdmailBranch extends Object{
  34. }
  35. }else{
  36. class QdmailBranch{
  37. }
  38. }
  39. if( !function_exists( 'qd_send_mail' ) ){
  40. function qd_send_mail( $type , $to = null, $subject = null , $content = null , $other_header = array() , $attach = null, $debug = 0 ){
  41. $type_org = $type;
  42. $mail = & Qdmail::getInstance();
  43. $mail->debug = $debug;
  44. if(!is_array($type)){
  45. $type = array('TYPE'=>$type);
  46. }
  47. list( $type , $link ) = $mail->keyUpper($type);
  48. $option = array();
  49. $return = array();
  50. $type = array_change_key_case( $type , CASE_UPPER ) ;
  51. $option = (isset($type['OPTION']) && is_array($type['OPTION'])) ? $type['OPTION'] : array(); $return = (isset($type['RETURN']) && is_array($type['RETURN'])) ? $type['RETURN'] : array();
  52. if(isset($type['SMTP'])){
  53. $option = array_merge($option,array('SMTP'=>true,'smtpServer'=>$type['SMTP']));
  54. }
  55. $type = isset($type['TYPE']) ? $type['TYPE']:'text';
  56. $_type=array('TEXT'=>'Text','HTML'=>'Html','DECO'=>'Deco' ,'DECOTEMPLATE'=>'DecoTemplate');
  57. $easy_method = isset($_type[strtoupper($type)]) ? 'easy'.$_type[strtoupper($type)]:'_';
  58. if(!method_exists($mail,$easy_method)){
  59. $mail -> errorGather('Illegal type \''.$type.'\'',__LINE__);
  60. return false;
  61. }
  62. $ret = $mail->{$easy_method}( $to , $subject , $content , $other_header , $attach , $option );
  63. foreach($return as $method => $value ){
  64. if(method_exists($mail,$method)){
  65. $type_org[$link['RETURN']][$method] = $mail -> {$method}($value);
  66. }
  67. }
  68. if(0!==count($return)){
  69. $type_org[$link['RETURN']]['qd_send_mail'] = $ret;
  70. $ret = $type_org;
  71. }
  72. return $ret;
  73. }
  74. }
  75. class QdmailBase extends QdmailBranch{
  76. //----------------------------
  77. // Default Language
  78. // If you do not Japanese
  79. // Please change this propaty for your Language and Encoding
  80. //----------------------------
  81. var $lang_def = "ja";
  82. var $encoding_def = "utf-8";
  83. var $detect_def = array('ASCII','JIS','UTF-8','EUC-JP','SJIS');
  84. var $mb_parameter_stack = null;
  85. var $united_charset = null;
  86. var $mime_encode_max = 75;
  87. //------------------------
  88. // Time Zone , Message Id
  89. //------------------------
  90. var $time_zone = null; // '+0900' in Japan
  91. var $message_id = true;
  92. var $salt = 'qdmail';
  93. var $message_id_right = null;
  94. //----------------------------
  95. // Line Feed Character & kana
  96. //----------------------------
  97. var $LFC = "\r\n";// Notice: CRLF ,If you failed, change to "\n"
  98. var $LFC_Qmail = null;
  99. //var $is_qmail = null;
  100. var $is_qmail = false;
  101. var $language = 'ja';
  102. var $kana = false; // kana header
  103. //----------
  104. // sysytem
  105. //----------
  106. var $kana_content_relation = false;
  107. var $name = 'Qdmail';
  108. var $version = '1.2.6b';
  109. var $xmailer = 'PHP-Qdmail';
  110. var $license = 'The_MIT_License';
  111. //--------------------
  112. // charset , encoding
  113. //--------------------
  114. var $charset_header = 'iso-2022-jp';
  115. var $charset_content = 'iso-2022-jp';
  116. var $charset_attach_filename = 'iso-2022-jp';
  117. var $content_transfer_enc_text = '7bit';
  118. var $content_transfer_enc_html = '7bit';
  119. var $detect_order = false;
  120. // var $detect_order = "iso-2022-jp,eucJP-win,UTF-8,SJIS-win,jis,ASCII";
  121. var $qdmail_system_charset = 'utf-8';
  122. var $force_change_charset = false;
  123. var $corres_charset = array(
  124. 'HEADER'=>'charset_header',
  125. 'BODY'=>'charset_content',
  126. 'ATTACH'=>'charset_attach_filename',
  127. 'TEXT'=>'content_transfer_enc_text',
  128. 'HTML'=>'content_transfer_enc_html',
  129. 'DETECT'=>'detect_order',
  130. 'SYSTEM'=>'qdmail_system_charset',
  131. ) ;
  132. //--------------------------
  133. // for address
  134. //--------------------------
  135. var $varidate_address_regex = '/[^@]+@[^@]+/';
  136. var $allow_blank_header = false;
  137. var $addr_many = array(
  138. 'TO' => true,
  139. 'CC' => true,
  140. 'BCC' => true,
  141. 'FROM' => false,
  142. 'REPLYTO'=> false
  143. );
  144. var $addr_head_name = array(
  145. 'TO' => 'To',
  146. 'CC' => 'Cc',
  147. 'BCC' => 'Bcc',
  148. 'FROM' => 'From',
  149. 'REPLYTO'=>'Reply-To'
  150. );
  151. var $header_must =array( 'TO' , 'FROM' , 'SUBJECT' );
  152. var $body_empty_allow = false;
  153. var $tokey = array(
  154. '_ADDR' => 'mail',
  155. '_NAME' => 'name',
  156. );
  157. //--------------
  158. // content_id
  159. //--------------
  160. var $content_id_include_attach_path = false ;
  161. var $content_id_only_filename = true ;
  162. //---------------
  163. // Once mode
  164. //---------------
  165. var $body_structure = array();
  166. var $body_build_once = false;
  167. var $body_already_build = false;
  168. var $attach_build_once = true;
  169. var $attach_already_build = false;
  170. //------------------------------
  171. // simple replace
  172. //------------------------------
  173. var $simple_replace = false;
  174. var $replace = array();
  175. var $replace_with_to_priority= true;
  176. var $replace_def = array();
  177. // simple replace command prefix
  178. var $rep_prefix = null;
  179. //---------
  180. // wordwrap
  181. //---------
  182. var $wordwrap_allow = false;
  183. var $wrap_prohibit_allow = false;
  184. var $wordwrap_length= 45 ;
  185. // inteligent wordwrap
  186. // false is that the word exist in the line ,
  187. // true is that the word must be the beginning of a line
  188. var $wrap_except = array(
  189. 'http://'=>false,
  190. 'code'=>true,
  191. );
  192. var $wrap_prohibit_top=',.;:–?!‼、。.))]}}〕〉》」』】〙〗〟’”»ヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎ‐〜?!';
  193. var $wrap_prohibit_end='(([{{〔〈《「『【〘〖‘“« ';
  194. var $wrap_prohibit = array();
  195. // multibyte wordwrap , by wordcount or by wordwidth
  196. var $wrap_width = true;
  197. // multibyte wordwidth compare by ascii
  198. var $mb_strwidth_magni = 2;
  199. //------------------
  200. // To Separate mode
  201. //------------------
  202. var $to_separate = false ;
  203. //----------------------------
  204. // html mail
  205. //----------------------------
  206. var $is_html = null ;
  207. var $auto_both = true ; // text & html
  208. var $inline_mode = false;
  209. var $deco_kind = null ; // number of $this->deco_def
  210. var $auto_deco_judge= false;
  211. var $no_inline_attach_structure = 0;
  212. var $deco_def_default = 0;
  213. var $deco_def =array(
  214. array(
  215. 'OPTION_NAME' => array( 'MHTML' , 'INLINE' , 'PC' ),
  216. 'STRUCTURE' => 1,
  217. '_CHARSET' => 'iso-2022-jp' ,
  218. 'ENC_TEXT' => '7bit',
  219. 'ENC_HTML' => 'QUOTED-PRINTABLE',
  220. 'HTML_EXTERNAL' => false,
  221. 'DISPOSITION' => true,
  222. ),
  223. array(
  224. 'OPTION_NAME' => array( 'DC' , 'DOCOMO' ),
  225. 'STRUCTURE' => 2,
  226. '_CHARSET' => 'iso-2022-jp',
  227. 'ENC_TEXT' => '7bit',
  228. 'ENC_HTML' => 'QUOTED-PRINTABLE',
  229. 'HTML_EXTERNAL' => array('this','stripCrlf'),
  230. 'DISPOSITION' => false,
  231. ),
  232. array(
  233. 'OPTION_NAME' => array( 'AU' ,'EZ', 'EZWEB'),
  234. 'STRUCTURE' => 3,
  235. '_CHARSET' => 'iso-2022-jp',
  236. 'ENC_TEXT' => '7bit',
  237. 'ENC_HTML' => 'QUOTED-PRINTABLE',
  238. 'HTML_EXTERNAL' => array('this','stripCrlf'),
  239. 'DISPOSITION' => true,
  240. ),
  241. array(
  242. 'OPTION_NAME' => array( 'SB' , 'SOFTBANK' ),
  243. 'STRUCTURE' => 4,
  244. '_CHARSET' => 'iso-2022-jp',
  245. 'ENC_TEXT' => '7bit',
  246. 'ENC_HTML' => 'QUOTED-PRINTABLE',
  247. 'HTML_EXTERNAL' => array('this','stripCrlf') ,
  248. 'DISPOSITION' => true ,
  249. ),
  250. array(
  251. 'OPTION_NAME' => array( 'EM','EMOBILE' ,'EMNET'),
  252. 'STRUCTURE' => 2,
  253. '_CHARSET' => 'iso-2022-jp',
  254. 'ENC_TEXT' => '7bit',
  255. 'ENC_HTML' => 'QUOTED-PRINTABLE',
  256. 'HTML_EXTERNAL' => array('this','stripCrlf') ,
  257. 'DISPOSITION' => true ,
  258. ),
  259. array(
  260. 'OPTION_NAME' => array( 'WL','WILLCOM' ,'POCKET'),
  261. 'STRUCTURE' => 2,
  262. '_CHARSET' => 'iso-2022-jp',
  263. 'ENC_TEXT' => '7bit',
  264. 'ENC_HTML' => 'QUOTED-PRINTABLE',
  265. 'HTML_EXTERNAL' => array('this','stripCrlf') ,
  266. 'DISPOSITION' => true ,
  267. ),
  268. array(
  269. 'OPTION_NAME' => array( 'TEMPLATE_DC' , 'TEMPLATE_DOCOMO' ,'TPL_DC'),
  270. 'STRUCTURE' => 5,
  271. '_CHARSET' => 'Shift_JIS',
  272. 'ENC_TEXT' => '8bit',
  273. 'ENC_HTML' => '8bit',
  274. 'HTML_EXTERNAL' => array('this','stripCrlf'),
  275. 'DISPOSITION' => false,
  276. 'BOUNDARY' => 'mime9DC9bdary',
  277. 'TOP' => array('Decomail-Template'),
  278. 'CID_PREFIX' => 'img_',
  279. 'CID_NUM_COL' => 3,
  280. ),
  281. array(
  282. 'OPTION_NAME' => array( 'TEMPLATE_AU','TPL_AU' ,'TPL_AU_2_0'),
  283. 'STRUCTURE' => 6,
  284. '_CHARSET' => 'iso-2022-jp',
  285. 'ENC_TEXT' => '7bit',
  286. 'ENC_HTML' => '7bit',
  287. 'HTML_EXTERNAL' => array('this','stripCrlf'),
  288. 'DISPOSITION' => false,
  289. 'BOUNDARY' => '--=_KDDI_NEXT_PART_0000',
  290. 'TOP' => array('KDDI_HTML_MAIL_2_0'),
  291. 'CID_PREFIX' => 'img_cid_',
  292. 'CID_NUM_COL' => 3,
  293. ),
  294. array(
  295. 'OPTION_NAME' => array( 'TEMPLATE_AU_1_0','TPL_AU_1_0' ,'TPL_AU_1_0'),
  296. 'STRUCTURE' => 6,
  297. '_CHARSET' => 'iso-2022-jp',
  298. 'ENC_TEXT' => '7bit',
  299. 'ENC_HTML' => '7bit',
  300. 'HTML_EXTERNAL' => array('this','stripCrlf'),
  301. 'DISPOSITION' => false,
  302. 'BOUNDARY' => '--=_KDDI_NEXT_PART_0000',
  303. 'TOP' => array('KDDI_HTML_MAIL_1_0'),
  304. 'CID_PREFIX' => 'img_cid_',
  305. 'CID_NUM_COL' => 3,
  306. ),
  307. array(
  308. 'OPTION_NAME' => array( 'TEMPLATE_SB','TPL_SB' ),
  309. 'STRUCTURE' => 5,
  310. '_CHARSET' => 'Shift_JIS',
  311. 'ENC_TEXT' => '8bit',
  312. 'ENC_HTML' => '8bit',
  313. 'HTML_EXTERNAL' => array('this','stripCrlf'),
  314. 'DISPOSITION' => false,
  315. 'BOUNDARY' => 'aremejkj15a14',
  316. 'TOP' => array('HTMLMail-Template-Version:1.0',
  317. 'HTMLMail-Template-Title:HTMLMail-Template',
  318. ''
  319. ),
  320. 'CID_PREFIX' => '',
  321. 'CID_NUM_COL' => 2,
  322. 'CID_AFTER' => '@areme.jp',
  323. ),
  324. );
  325. var $structure =array(
  326. // no inline attachment
  327. 0 => array(
  328. 'multipart/mixed' => array(
  329. 'multipart/alternative'=>array(
  330. 'html' => 1,
  331. 'plain' => 1,
  332. 'OMIT' => true,
  333. ),
  334. 'image' => 'BOTH', // Available Inline
  335. 'OMIT' => true,
  336. ),
  337. 'OMIT' => true,
  338. ),
  339. // PC inline HTML
  340. 1 => array(
  341. 'multipart/mixed' => array(
  342. 'multipart/alternative'=>array(
  343. 'multipart/related' => array(
  344. 'html' => 1,
  345. 'image' => 'INLINE',
  346. 'OMIT' => true,
  347. ),
  348. 'plain' => 1,
  349. 'OMIT' => true,
  350. ),
  351. 'image' => 'NOT_INLINE', // not inline
  352. 'OMIT' => true,
  353. ),
  354. 'OMIT' => true,
  355. ),
  356. 2 => array(
  357. 'multipart/mixed' => array(
  358. 'multipart/related'=>array(
  359. 'multipart/alternative' => array(
  360. 'plain' => 1,
  361. 'html' => 1,
  362. 'OMIT' => false,
  363. ),
  364. 'image' => 'INLINE',
  365. 'OMIT' => false,
  366. ),
  367. 'OMIT' => false,
  368. 'image' => 'NOT_INLINE',
  369. ),
  370. 'OMIT' => false,
  371. ),
  372. 3 => array(
  373. 'multipart/mixed' => array(
  374. 'multipart/alternative' => array(
  375. 'plain' => 1,
  376. 'html' => 1,
  377. 'OMIT' => false,
  378. ),
  379. 'image' => 'BOTH',
  380. 'OMIT' => false,
  381. ),
  382. 'OMIT' => false,
  383. ),
  384. 4 => array(
  385. 'multipart/related'=>array(
  386. 'multipart/alternative' => array(
  387. 'plain' => 1,
  388. 'html' => 1,
  389. 'OMIT' => false,
  390. ),
  391. 'image' => 'INLINE',
  392. 'OMIT' => false,
  393. ),
  394. 'image' => 'NOT_INLINE',
  395. 'OMIT' => false,
  396. ),
  397. 5 => array(
  398. 'multipart/related'=>array(
  399. 'plain' => 1,
  400. 'html' => 1,
  401. 'image' => 'INLINE',
  402. 'OMIT' => false,
  403. ),
  404. 'OMIT' => false,
  405. ),
  406. 6 => array(
  407. 'multipart/mixed'=>array(
  408. 'plain' => 1,
  409. 'html' => 1,
  410. 'image' => 'INLINE',
  411. 'OMIT' => false,
  412. ),
  413. 'OMIT' => false,
  414. ),
  415. );
  416. var $deco_judge = array(
  417. 'docomo.ne.jp' => 'DC',
  418. 'softbank.ne.jp' => 'SB',
  419. 'i.softbank.ne.jp' => 'SB',
  420. 'disney.ne.jp' => 'SB',
  421. 'vodafone.ne.jp' => 'SB',
  422. 'ezweb.ne.jp' => 'AU',
  423. 'emnet.ne.jp' => 'EM',
  424. 'pdx.ne.jp' => 'WL',
  425. 'gmail.com' => 'DC',
  426. );
  427. //------------------
  428. // using address and content
  429. //------------------
  430. var $to = array() ;
  431. var $from = array() ;
  432. var $cc = array() ;
  433. var $bcc = array() ;
  434. var $done = array() ;
  435. var $undone = array() ;
  436. var $replyto = array() ;
  437. var $recipient = array() ;
  438. var $allways_bcc = null ;
  439. var $header = array() ;
  440. var $other_header = array() ;
  441. var $header_content_type = array();
  442. var $content = array(
  443. 'TEXT'=>array(
  444. 'CONTENT' => null,
  445. 'LENGTH' => null,
  446. '_CHARSET' => null,
  447. 'ENC' => null,
  448. '_ORG_CHARSET' => null,
  449. ),
  450. 'HTML'=>array(
  451. 'CONTENT' => null,
  452. 'ORG_CONTENT' => null,
  453. 'LENGTH' => null,
  454. '_CHARSET' => null,
  455. 'ENC' => null,
  456. '_ORG_CHARSET' => null,
  457. ),
  458. );
  459. var $header_for_mailfunction_to;
  460. var $header_for_mailfunction_subject;
  461. var $header_for_mailfunction_other;
  462. var $content_for_mailfunction;
  463. var $header_for_smtp_array;
  464. var $content_all_for_smtp;
  465. var $header_for_smtp;
  466. //--------------
  467. // attachament
  468. //--------------
  469. var $attach = array();
  470. var $attach_path = null;
  471. var $auto_ext = true ; // mimetypes
  472. var $content_id_fix = false;
  473. //------------------------
  474. // Mailer
  475. //-------------------------
  476. var $mailer = 'mail';
  477. //------------------------
  478. // Sendmail
  479. //-------------------------
  480. var $sendmail = false ;
  481. var $sendmail_path = null;
  482. //------------------------
  483. // SMTP
  484. //-------------------------
  485. var $smtp = false ;
  486. var $smtp_object = null;
  487. var $smtp_loglevel_link = false;
  488. var $smtp_server = array(
  489. 'host' => null ,
  490. 'port' => 25 ,
  491. 'from' => null,
  492. 'user' => null,
  493. 'pass' => null,
  494. 'protocol' => null,
  495. 'pop_host' => null,
  496. 'pop_user' => null,
  497. 'pop_pass' => null,
  498. );
  499. //------------------------
  500. // render Mode
  501. //------------------------
  502. var $render_mode = false;
  503. var $size = array();
  504. //------------------------
  505. // Priority
  506. //------------------------
  507. var $priority = null;
  508. var $priority_def =array(
  509. 'X-Priority' => array( 'HIGH' => 1 , 'NORMAL' => 3 , 'LOW' =>5 ),
  510. 'X-MsMail-Priotiry' => array( 'HIGH'=>'High' , 'NORMAL'=>'Normal' , 'LOW'=>'Low' ),
  511. 'Priotiry' => array( 'HIGH'=>'urgent' , 'NORMAL' => 'normal' , 'LOW'=> 'non-urgent' ),
  512. 'Importance' => array( 'HIGH' =>'High' , 'NORMAL'=>'Normal' ,'LOW' =>'Low' ),
  513. );
  514. //------------------------
  515. // signed
  516. //------------------------
  517. var $sign = false;
  518. var $smime = false;
  519. var $pgp = false;
  520. var $private_key_file = 'private.pem';
  521. var $certificate_file = 'cert.pem';
  522. var $certificate_pass = null;
  523. var $certificate_file_path = null;
  524. var $certificate_temp_path = null;
  525. var $certificate_file_path_win = 'c:\cert';
  526. var $certificate_temp_path_win = 'c:\temp';
  527. var $certificate_file_path_unix = '/user/local/cert';
  528. var $certificate_temp_path_unix = '/tmp';
  529. //------------------------
  530. // etc
  531. //------------------------
  532. var $temporary_path = null;
  533. var $simple_attach = false;
  534. var $keep_parameter = array(false);
  535. var $mta_option = null ;
  536. var $is_create = false;
  537. var $address_validation_method = array('this','validateAddr');
  538. var $boundary_base_degit= 2 ;
  539. var $stack_construct = null ;
  540. var $start_time = null;
  541. var $framework = null;
  542. //-------------------------------
  543. // logs
  544. // 0 is nolog,
  545. // 1 is simple(Message 'Success' & recipt e-mail@address ),
  546. // 2 is including header data,
  547. // 3 is including fulldata,
  548. //------------------------------
  549. var $log_level = 0 ;
  550. var $log_level_max = 3 ;
  551. var $log_path = './';
  552. var $log_filename = 'qdmail.log';
  553. var $log_append = 'a' ;
  554. var $log_dateformat = 'Y-m-d H:i:s';
  555. var $log_LFC = "\n";
  556. // -------------------------------
  557. // error & error logs
  558. // 0 is nolog,
  559. // 1 is simple,
  560. // 2 is including header data,
  561. // 3 is inc fulldata
  562. //--------------------------------
  563. var $error = array();
  564. var $error_stack = array();
  565. var $error_display = true;
  566. var $errorlog_level = 0 ;
  567. var $errorlog_level_max = 3 ;
  568. var $errorlog_path = './';
  569. var $errorlog_filename= 'qbmail_error.log';
  570. var $errorlog_append= 'a' ;
  571. var $ignore_error = false ;
  572. //----------------
  573. // debug
  574. // 0 is no debug mode & really sending ,
  575. // 1 is showing header&body & really sending ,
  576. // 2 is no sending & showing header&body and some vars
  577. //----------------
  578. var $debug = 0 ;
  579. var $debug_report = false;
  580. var $debug_report_path = './';
  581. var $debug_echo_charset= true;
  582. //****************************************************
  583. // Methods
  584. //****************************************************
  585. //--------------------------------
  586. // constructor set error display
  587. // $charset_def = null,
  588. // $error_display = true
  589. // $mail -> (&) new Qdmail( Charset , Encoding , DetectOrder , error_display );
  590. //--------------------------------
  591. function __construct( $param = null ){
  592. $this->stack_construct = $param ;
  593. if( !empty( $param[0] ) && !empty( $param[1] ) ){
  594. $this->charset( $param[0] , $param[1] );
  595. }elseif( !empty( $param[0] ) ){
  596. $this->charset( $param[0] );
  597. }
  598. if( !empty( $param[2] ) ){
  599. $this->detect_order = $param[1];
  600. }
  601. if( false !== $this->detect_order ){
  602. $this->qd_detect_order( $this->detect_order );
  603. }
  604. if( !empty( $param[3] ) ){
  605. $this->error_display = $param[2];
  606. }
  607. if(is_null($this->LFC)){
  608. $this->LFC = chr(13) . chr(10);
  609. }
  610. if(is_null($this->LFC_Qmail)){
  611. $this->LFC_Qmail = chr(10);
  612. }
  613. if($this->isQmail()){
  614. $this->LFC = $this->LFC_Qmail;
  615. }
  616. $this->optionNameLink();
  617. $this->wordwrapProhibitConstruct();
  618. $this->sendmail_path = ini_get("sendmail_path");
  619. }
  620. function & getInstance(){
  621. static $instance = array();
  622. if( isset($instance[0]) && is_object($instance[0]) ){
  623. $keep = $instance[0]->keep_parameter;
  624. if( is_string($keep[0]) ){
  625. $stack = array();
  626. foreach($keep as $method){
  627. if( !is_string( $method ) || !method_exists( $instance[0] , $method ) ){
  628. continue;
  629. }
  630. $stack[$method] = $instance[0]->{$method}();
  631. }
  632. $instance[0] -> reset();
  633. foreach($stack as $method => $value){
  634. $instance[0]->{$method}($value);
  635. }
  636. }elseif( true !== $keep[0] ){
  637. $instance[0] -> reset();
  638. }
  639. return $instance[0];
  640. }
  641. $instance[0] = & new Qdmail();
  642. return $instance[0];
  643. }
  644. //--------------------------
  645. // Decoration Mail Template
  646. //--------------------------
  647. function makeDecoTemplate( $deco_kind , $content ){
  648. if(false===($this->deco_kind=$this->decoSelect( $deco_kind ))){
  649. return $this->errorGather('Illegal Decoration Kind \''.$deco_kind.'\'',__LINE__);
  650. }
  651. $DECO = new QdDeco;
  652. $DECO -> template($content);
  653. $DECO -> decode();
  654. $content = $DECO -> get('HTML');
  655. $attach = $DECO -> get('ATTACH');
  656. $this -> renderMode( true );
  657. $this -> to('dummy@example.com');
  658. $this -> from('dummy@example.com');
  659. $this -> subject('dummy_subject');
  660. $this->body = null;
  661. $this->after_id = null;
  662. $this->content_id_fix = true;
  663. $this->is_html = 'HTML';
  664. $count = 0;
  665. $content = $this->qd_convert_encoding($content,'utf-8',$this->qd_detect_encoding($content));
  666. $content=preg_replace('/\r?\n/','',$content);
  667. foreach($attach as $key => $att){
  668. if( empty( $attach[$key]['CONTENT-ID'] ) ){
  669. continue;
  670. }
  671. $aft = isset($this->deco_def[$this->deco_kind]['CID_AFTER']) ? $this->deco_def[$this->deco_kind]['CID_AFTER']:'';
  672. $prefix = isset($this->deco_def[$this->deco_kind]['CID_PREFIX']) ? $this->deco_def[$this->deco_kind]['CID_PREFIX']:'';
  673. $col_num = isset($this->deco_def[$this->deco_kind]['CID_NUM_COL']) ? $this->deco_def[$this->deco_kind]['CID_NUM_COL']:3;
  674. $ct = '00'.$count++;
  675. $start = (strlen($ct)-$col_num) < 0 ? 0:strlen($ct)-$col_num;
  676. $end = strlen($ct)-$start;
  677. $new_cid = $prefix
  678. . substr($ct,$start,$end)
  679. . $aft;
  680. $content=preg_replace('/<\s*IMG\s+SRC\s*=\s*"cid:'.$attach[$key]['CONTENT-ID'].'"/is','<IMG SRC="cid:'.$new_cid.'"',$content);
  681. $attach[$key]['CONTENT-ID'] = $new_cid;
  682. }
  683. $this->html( $content , null , null , 'utf-8' );
  684. if( 0 < count($attach) ){
  685. $this->attach( $attach );
  686. }
  687. $this->createMail(
  688. $this->deco_def[$this->deco_kind]['BOUNDARY'],
  689. true
  690. );
  691. $header = '';
  692. foreach($this->deco_def[$this->deco_kind]['TOP'] as $line){
  693. $header .= $line .$this->LFC;
  694. }
  695. $header .= 'MIME-Version: 1.0' . $this->LFC
  696. . 'Content-type: ' . key($this->structure[$this->deco_def[$this->deco_kind]['STRUCTURE']])
  697. . '; boundary="'.$this->deco_def[$this->deco_kind]['BOUNDARY'] . '"'
  698. . $this->LFC;
  699. return $header . $this->LFC . $this -> smtpDataBody() . $this->LFC ;
  700. }
  701. //-------------------
  702. // Easy Base
  703. //-------------------
  704. function easy( $type , $to , $subject , $content , $other_header = array() , $attach = null ){
  705. if(is_null($other_header)){
  706. $other_header=array();
  707. }
  708. $this->resetHeaderBody();
  709. $option_return = array();
  710. if( is_array($type) ){
  711. $type = array_change_key_case( $type , CASE_UPPER );
  712. if( isset( $type['SMTP'] ) ){
  713. $this->smtp( true );
  714. $this->smtpServer( $type['SMTP'] );
  715. }
  716. if(isset( $type['OPTION'] )){
  717. $type['OPTION'] = array_change_key_case( $type['OPTION'] , CASE_UPPER );
  718. foreach($type['OPTION'] as $method => $param ){
  719. if(method_exists($this,$method)){
  720. $option_return[$method] = $this->{$method}($param);
  721. }
  722. }
  723. }
  724. $type = isset( $type['TYPE'] ) ? $type['TYPE'] : 'TEXT' ;
  725. }
  726. if( (empty($to) && ( !empty($subject) || !empty($content) ))){
  727. return $this->errorGather('Parameter Specified Error',__LINE__);
  728. }elseif( empty($to) ){
  729. return $option_return;
  730. }
  731. if( 'TEXT' == strtoupper( $type ) || 'HTML' == strtoupper( $type ) ){
  732. $type=strtolower( $type );
  733. }else{
  734. $this->error[]='Illegal spcify \'type\' in '.$type.' .'.__LINE__;
  735. return $this->errorGather();
  736. }
  737. $to = is_string($to) ? array($to) : $to ;
  738. $other_header = is_string($other_header) ? array('From' => $other_header) : $other_header ;
  739. list($other_header_temp , $link ) = $this->keyUpper( $other_header );
  740. if(!isset($other_header_temp['FROM'])){
  741. $fromAddr = null;
  742. if( isset($other_header[0]) ){
  743. $fromAddr = $other_header[0];
  744. unset($other_header[0]);
  745. }
  746. $fromName = null;
  747. if(isset($other_header[1])){
  748. $fromName = $other_header[1];
  749. unset($other_header[1]);
  750. }
  751. if(!empty($fromAddr)){
  752. $other_header = array_merge( $other_header,array('FROM'=>array( $fromAddr , $fromName )));
  753. }
  754. }
  755. $other_header = array_merge(array('TO'=>$to),$other_header);
  756. $section = array('TO'=>'to','CC'=>'cc','BCC'=>'bcc','REPLY-TO'=>'replyto','FROM'=>'from');
  757. list($other_header_temp , $link ) = $this->keyUpper( $other_header );
  758. foreach($other_header_temp as $key => $other_head){
  759. if(isset($section[$key])){
  760. $method = $section[$key];
  761. $this -> {$method}( $other_head , null );
  762. }else{
  763. $this -> addHeader( $link[$key] , $other_head );
  764. }
  765. }
  766. $this->subject( $subject );
  767. $this->{$type}( $content );
  768. if( isset( $attach ) ){
  769. $this->attach( $attach , $add = false , $this->inline_mode );
  770. }
  771. return $this->send();
  772. }
  773. function easyText( $to , $subject , $content , $other_header = array() , $attach = null , $option = array() ){
  774. return $this->easy( array('TYPE'=>'text','OPTION'=>$option) , $to , $subject , $content , $other_header , $attach );
  775. }
  776. function easyHtml( $to , $subject , $content , $other_header = array() , $attach = null , $option = array() ){
  777. return $this->easy( array('TYPE'=>'html','OPTION'=>$option) , $to , $subject , $content , $other_header , $attach );
  778. }
  779. function easyReplace( $to , $subject , $content , $other_header = array() , $attach = null , $option = array() ){
  780. $this->simpleReplace( true );
  781. $type = 'text';
  782. if(0!==count($option)){
  783. $option = array_change_key_case( $option , CASE_UPPER );
  784. $type = ( 'HTML' === strtoupper( $option['TYPE']) ) ? 'html' : $type ;
  785. }
  786. $this->easy( array('TYPE'=>$type,'OPTION'=>$option) , $to , $subject , $content , $other_header , $attach );
  787. }
  788. function easyDeco( $to , $subject , $content , $other_header = array() , $attach = null , $option = array() ){
  789. if( isset( $attach ) ){
  790. $this->inline_mode=true;
  791. }
  792. $this->autoDecoJudge( true );
  793. $this->toSeparate( true );
  794. return $this->easy( array('TYPE'=>'html','OPTION'=>$option) , $to , $subject , $content , $other_header , $attach );
  795. }
  796. function easyDecoTemplate( $to , $subject , $template , $other_header = array() , $attach = null , $option = array() ){
  797. if(is_null($attach)){
  798. $attach = array();
  799. }
  800. $DECO = new QdDeco;
  801. $DECO -> template($template);
  802. $DECO -> decode();
  803. $content = $DECO -> get('HTML');
  804. $text = $DECO -> get('PLAIN');
  805. if(!empty($text)){
  806. $this->text($text);
  807. }
  808. $att = $DECO ->get('ATTACH');
  809. $attach = array_merge($att,$attach);
  810. return $this->easyDeco( $to , $subject , $content , $other_header , $attach , $option );
  811. }
  812. function easyDecoRep( $to , $subject , $content , $other_header = array() , $attach = null , $option = array() ){
  813. $this->simpleReplace( true );
  814. return $this->easyDeco($to , $subject , $content , $attach , $option , $option);
  815. }
  816. function easyOption( $to , $subject = null , $content = null , $other_header = array() , $attach = null , $option = array() ){
  817. if(!is_array($to)){
  818. $option = array( $to => $subject );
  819. }else{
  820. $option = $to;
  821. }
  822. return $this->easy( array('TYPE'=>'option','OPTION'=>$option) , $to , $subject , $content , $other_header , $attach );
  823. }
  824. /*
  825. * Notice: Before use $this->optionNameLink(); by Constractor
  826. */
  827. //
  828. //---------------------------------------
  829. // something change mode
  830. //---------------------------------------
  831. // Keys must lowercase , because of PHP4's
  832. var $property_type = array(
  833. 'auto_both' => 'bool' ,
  834. 'to_separate' => 'bool' ,
  835. 'simple_replace' => 'bool' ,
  836. 'auto_deco_judge' => 'bool' ,
  837. 'auto_ext' => 'bool' ,
  838. 'body_empty_allow' => 'bool' ,
  839. 'ignore_error' => 'bool' ,
  840. 'wrap_width' => 'bool' ,
  841. 'wordwrap_allow' => 'bool' ,
  842. 'wrap_prohibit_allow'=> 'bool' ,
  843. 'force_change_charset' => 'bool' ,
  844. 'error_display' => 'bool' ,
  845. 'sendmail' => 'bool' ,
  846. 'smtp' => 'bool' ,
  847. 'smtp_loglevel_link'=> 'bool' ,
  848. 'inline_mode' => 'bool' ,
  849. 'replace_with_to_priority'=> 'bool' ,
  850. 'attach_build_once' => 'bool' ,
  851. 'body_build_once' => 'bool' ,
  852. 'kana' => 'bool' ,
  853. 'render_mode' => 'bool' ,
  854. 'smime' => 'bool' ,
  855. 'pgp' => 'bool' ,
  856. 'simple_attach' => 'bool' ,
  857. 'message_id' => 'bool' ,
  858. 'allow_blank_header'=> 'bool' ,
  859. 'sign' => 'string' ,
  860. 'keep_parameter' => 'array' ,
  861. 'attach_path' => 'string' ,
  862. 'mta_option' => 'string' ,
  863. 'rep_prefix' => 'string' ,
  864. 'log_path' => 'string' ,
  865. 'errorlog_path' => 'string' ,
  866. 'log_filename' => 'string' ,
  867. 'errorlog_filename' => 'string' ,
  868. 'allways_bcc' => 'string' ,
  869. 'wrap_prohibit_top' => 'string' ,
  870. 'wrap_prohibit_end' => 'string' ,
  871. 'framework' => 'string' ,
  872. 'priority' => 'string' ,
  873. 'certificate_file' => 'string' ,
  874. 'certificate_file_path' => 'string' ,
  875. 'certificate_temp_path' => 'string' ,
  876. 'time_zone' => 'string' ,
  877. 'private_key_file' => 'string' ,
  878. 'certificate_pass' => 'string' ,
  879. 'message_id_right' => 'string' ,
  880. 'sendmail_path' => 'string' ,
  881. 'temporary_path' => 'string' ,
  882. 'united_charset' => 'string' ,
  883. 'varidate_address_regex'=> 'string' ,
  884. 'mb_strwidth_magni' => 'numeric' ,
  885. 'log_dateformat' => 'numeric' ,
  886. 'log_level' => 'numeric' ,
  887. 'errorlog_level' => 'numeric' ,
  888. 'mime_encode_max' => 'numeric' ,
  889. 'smtp_server' => 'array' ,
  890. 'address_validation_method'=> 'array',
  891. );
  892. var $method_property = array();
  893. function optionNameLink(){
  894. foreach($this->property_type as $prop => $type ){
  895. $method_low = strtolower( str_replace( '_' , '' , $prop ) );
  896. $this->method_property[$method_low] = $prop;
  897. }
  898. }
  899. function option( $option , $line = null , $min = null , $max = null ){
  900. $ret = array();
  901. if( !is_null( $line ) ){
  902. $line = '-' . $line ;
  903. }
  904. if(!is_array($option)){
  905. return $this->errorSpecify( __FUNCTION__, __LINE__ );
  906. }
  907. foreach( $option as $key => $value ){
  908. if( !isset( $this->method_property[strtolower($key)] ) ){
  909. return $this->errorSpecify( __FUNCTION__ . '-' .$key , __LINE__ . $line );
  910. }
  911. $property_name = $this->method_property[strtolower($key)];
  912. if( is_null( $value ) ){
  913. $ret[] = $this->{$property_name} ;
  914. continue ;
  915. }
  916. $err = false;
  917. switch( $this->property_type[$property_name] ){
  918. case 'bool':
  919. if( is_bool( $value ) ){
  920. $this->{$property_name} = $value ;
  921. $ret[0] = true ;
  922. }else{
  923. return $this->errorSpecify( __FUNCTION__ . '-' .$key , __LINE__ . $line );
  924. }
  925. break;
  926. case 'string':
  927. if( '' === $value ){
  928. $this->{$property_name} = null ;
  929. $ret[0] = true ;
  930. break ;
  931. }
  932. if( is_string( $value ) ){
  933. $this->{$property_name} = $value ;
  934. $ret[0] = true ;
  935. }else{
  936. return $this->errorSpecify( __FUNCTION__ . '-' .$key , __LINE__ . $line );
  937. }
  938. break;
  939. case 'numeric':
  940. if( !is_numeric( $value ) || ( isset( $min ) && ( $value < $min ) ) || ( isset( $max ) && ( $value > $max ) ) ){
  941. return $this->errorSpecify( __FUNCTION__ . '-' .$key , __LINE__ . $line );
  942. }else{
  943. $this->{$property_name} = $value ;
  944. $ret[0] = true ;
  945. }
  946. break;
  947. case 'array':
  948. if( !is_array( $value ) ){
  949. $value = array( $value );
  950. }
  951. if( true===$min ){
  952. $this->{$property_name} = array_merge( $this->{$property_name} , $value );
  953. }else{
  954. $this->{$property_name} = $value ;
  955. }
  956. $ret[0] = true ;
  957. if( true === $max ){
  958. $this->{$property_name} = array_change_key_case( $this->{$property_name} , CASE_UPPER );
  959. }
  960. break;
  961. default:
  962. return $this->errorSpecify( __FUNCTION__ . '-' .$key , __LINE__ . $line );
  963. break;
  964. }
  965. }
  966. if( 0 === count( $ret ) ){
  967. return $this->errorSpecify( __FUNCTION__ , __LINE__ );
  968. }elseif( 1 === count( $ret ) ){
  969. return array_shift( $ret );
  970. }else{
  971. return $ret ;
  972. }
  973. }
  974. function autoBoth( $bool = null ){
  975. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  976. }
  977. function toSeparate( $bool = null ){
  978. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  979. }
  980. function simpleReplace( $bool = null ){
  981. $this->toSeparate( $bool );
  982. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  983. }
  984. function autoDecoJudge( $bool = null ){
  985. $this->attachBuildOnce( !$bool );
  986. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  987. }
  988. function autoExt( $bool = null ){
  989. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  990. }
  991. function bodyEmptyAllow( $bool = null ){
  992. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  993. }
  994. function ignoreError( $bool = null ){
  995. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  996. }
  997. function forceChangeCharset( $bool = null ){
  998. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  999. }
  1000. function errorDisplay( $bool = null ){
  1001. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1002. }
  1003. function sendmail( $bool = null ){
  1004. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1005. }
  1006. function smtp( $bool = null ){
  1007. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1008. }
  1009. function smtpLoglevelLink( $bool = null ){
  1010. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1011. }
  1012. function inlineMode( $bool = null ){
  1013. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1014. }
  1015. function replaceWithToPriority( $bool = null ){
  1016. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1017. }
  1018. function attachBuildOnce( $bool = null ){
  1019. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1020. }
  1021. function bodyBuildOnce( $bool = null ){
  1022. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1023. }
  1024. function kana( $bool = null ){
  1025. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1026. }
  1027. function keepParameter( $bool = null ){
  1028. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1029. }
  1030. function renderMode( $bool = null ){
  1031. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1032. }
  1033. function simpleAttach( $bool = null ){
  1034. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1035. }
  1036. function messageId( $bool = null ){
  1037. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1038. }
  1039. function allowBlankHeader( $bool = null ){
  1040. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1041. }
  1042. function smime( $bool = null ){
  1043. $fg = $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1044. if(!extension_loaded ( 'openssl' )){
  1045. $this->smime = false;
  1046. if(!$bool){
  1047. return false;
  1048. }
  1049. }
  1050. return $fg;
  1051. }
  1052. function pgp( $bool = null ){
  1053. // future
  1054. return true;
  1055. }
  1056. function sign( $string = null ){
  1057. if(false===$string){
  1058. $this->smime = false;
  1059. $this->pgp = false;
  1060. $this->sign = false;
  1061. return true;
  1062. }
  1063. if(empty($string)){
  1064. return $this->sign;
  1065. }
  1066. $string = strtoupper($string);
  1067. if('S/MIME'==$string){
  1068. $this->smime(true);
  1069. }elseif('PGP'==$string){
  1070. $this->pgp(true);
  1071. }else{
  1072. return false;
  1073. }
  1074. $fg = $this->option( array( __FUNCTION__ => $string ) ,__LINE__);
  1075. return $fg;
  1076. }
  1077. function size( $kind = null ){
  1078. if(empty($this->header_for_smtp)){
  1079. $stack = $this->render_mode;
  1080. $this->render_mode = true;
  1081. $fg = $this->send();
  1082. $this->render_mode = $stack;
  1083. }
  1084. $this->size['ALL'] = strlen( bin2hex( $this->header_for_smtp . $this->LFC . $this->content_for_mailfunction )) / 2;
  1085. $this->size['HEADER'] = strlen( bin2hex( $this->header_for_smtp )) / 2;
  1086. $this->size['BODY'] = strlen( bin2hex( $this->content_for_mailfunction )) / 2;
  1087. if(is_null($kind)){
  1088. return $this->size;
  1089. }
  1090. $kind = strtoupper( $kind );
  1091. if(isset($this->size[$kind])){
  1092. return $this->size[$kind];
  1093. }
  1094. return false;
  1095. }
  1096. function sizeAll(){
  1097. return $this->size('ALL');
  1098. }
  1099. function sizeHeader(){
  1100. return $this->size('HEADER');
  1101. }
  1102. function sizeBody(){
  1103. return $this->size('BODY');
  1104. }
  1105. function smtpData(){
  1106. if(empty($this->header_for_smtp)){
  1107. $stack = $this->render_mode;
  1108. $this->render_mode = true;
  1109. $fg = $this->send();
  1110. $this->render_mode = $stack;
  1111. }
  1112. return $this->header_for_smtp . $this->LFC . $this->content_for_mailfunction ;
  1113. }
  1114. function smtpDataBody(){
  1115. if(empty($this->content_for_mailfunction)){
  1116. $stack = $this->render_mode;
  1117. $this->render_mode = true;
  1118. $fg = $this->send();
  1119. $this->render_mode = $stack;
  1120. }
  1121. return $this->content_for_mailfunction ;
  1122. }
  1123. function isQmail(){
  1124. if(!is_null($this->is_qmail)){
  1125. return $this->is_qmail;
  1126. }
  1127. $this->is_qmail = false;
  1128. $ret = ini_get ( 'sendmail_path' );
  1129. if(false !== strpos($ret,'qmail')){
  1130. $this->is_qmail = true;
  1131. }
  1132. $sendmail_path = ini_get('sendmail_path');
  1133. if(false !== @system($sendmail_path.' -d0.1 < /dev/null > /dev/null',$ret)){
  1134. if(is_array($ret)){
  1135. $ret = reset($ret);
  1136. }
  1137. $code = (int) substr($ret,0,3);
  1138. if( 100 === $code || 111 === $code){
  1139. $this->is_qmail = true;
  1140. }
  1141. }
  1142. return $this->is_qmail ;
  1143. }
  1144. function lineFeed( $LFC = null ){
  1145. if(is_null($LFC)){
  1146. return $this->LFC;
  1147. }
  1148. if(preg_match('/[\r|\n|\r\n]/is',$LFC)){
  1149. $this->LFC = $LFC;
  1150. return true;
  1151. }else{
  1152. return false;
  1153. }
  1154. }
  1155. function isWin(){
  1156. return false!==strpos(PHP_OS,'WIN');
  1157. }
  1158. //---------------------------------------
  1159. // something change mode
  1160. //---------------------------------------
  1161. function whichTextHtml( $which ){
  1162. $which = strtoupper( $which );
  1163. if( 'TEXT' == $which ){
  1164. $this->is_html='TEXT';
  1165. }elseif( 'HTML' == $which ){
  1166. $this->is_html='HTML';
  1167. }elseif( 'BOTH' == $which ){
  1168. $this->is_html='BOTH';
  1169. }
  1170. }
  1171. function allwaysBcc( $option = null ){
  1172. if( is_null( $option ) ){
  1173. return $this->allways_bcc ;
  1174. }
  1175. if( $this->option( array( __FUNCTION__ => $option ) ,__LINE__) ){
  1176. $fg = $this->extractAddr( $this->allways_bcc ) ;
  1177. }
  1178. if( $this->errorGather() && $fg && !empty($this->allways_bcc) ){
  1179. return true ;
  1180. }else{
  1181. $this->allways_bcc = array();
  1182. return false ;
  1183. }
  1184. }
  1185. function priority( $option = null ){
  1186. $fg=$this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1187. $priority = strtoupper($option);
  1188. if(empty($priority)){
  1189. return $fg;
  1190. }
  1191. $kind = array('HIGH'=>1,'NORMAL'=>1,'LOW'=>1);
  1192. if( !isset( $kind[$priority] ) ){
  1193. return $this->errorGather('Illegal Priority Name \''.$option.'\'',__LINE__);
  1194. }
  1195. foreach($this->priority_def as $header_name => $values){
  1196. $this->addHeader($header_name,$values[$priority]);
  1197. }
  1198. return $this->errorGather();
  1199. }
  1200. function certificatePass( $option = null ){
  1201. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1202. }
  1203. function certificateFilePath( $option = null ){
  1204. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1205. }
  1206. function certificateTempPath( $option = null ){
  1207. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1208. }
  1209. function certificateFile( $option = null ){
  1210. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1211. }
  1212. function privateKeyFile( $option = null ){
  1213. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1214. }
  1215. function framework( $option = null ){
  1216. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1217. }
  1218. function attachPath( $option = null ){
  1219. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1220. }
  1221. function timeZone( $option = null ){
  1222. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1223. }
  1224. function messageIdRight( $option = null ){
  1225. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1226. }
  1227. function mtaOption( $option = null ){
  1228. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1229. }
  1230. function unitedCharset( $option = null ){
  1231. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1232. }
  1233. function varidateAddressRegex( $option = null ){
  1234. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1235. }
  1236. function sendmailPath( $option = null ){
  1237. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1238. }
  1239. function temporaryPath( $option = null ){
  1240. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1241. }
  1242. function logPath( $option = null ){
  1243. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1244. }
  1245. function errorlogPath( $option = null ){
  1246. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1247. }
  1248. function logDateFormat( $option = null ){
  1249. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1250. }
  1251. function logFilename( $option = null ){
  1252. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1253. }
  1254. function errorlogFilename( $option = null ){
  1255. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1256. }
  1257. function logLevel( $option = null ){
  1258. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__, 0 , $this->log_level_max );
  1259. }
  1260. function errorlogLevel( $option = null ){
  1261. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__, 0 , $this->errorlog_level_max );
  1262. }
  1263. function mimeEncodeMax( $option = null ){
  1264. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1265. }
  1266. function smtpServer( $array = null ){
  1267. return $this->option( array( __FUNCTION__ => $array ) ,__LINE__, true , true );
  1268. }
  1269. function addressValidationMethod( $array = null ){
  1270. return $this->option( array( __FUNCTION__ => $array ) ,__LINE__, false , true );
  1271. }
  1272. //------------------
  1273. //version
  1274. //------------------
  1275. function version(){
  1276. return $this->version;
  1277. }
  1278. //------------------
  1279. //mb_ wrapper
  1280. //------------------
  1281. function qd_detect_encoding( $word ){
  1282. if(!is_null($this->united_charset)){
  1283. return $this->united_charset;
  1284. }else{
  1285. return mb_detect_encoding( $word , mb_detect_order() , true );
  1286. }
  1287. }
  1288. function qd_convert_encoding( $word , $target_chrset , $org_charset = null ){
  1289. if(empty($org_charset)){
  1290. $org_charset = $this->qd_detect_encoding( $word );
  1291. }
  1292. if(empty($org_charset)){
  1293. return $word;
  1294. }
  1295. if( strtoupper( $target_chrset ) === strtoupper( $org_charset ) ){
  1296. return $word;
  1297. }
  1298. if('ASCII'===strtoupper( $target_chrset ) || 'ASCII'===strtoupper( $org_charset )){
  1299. return $word;
  1300. }
  1301. return mb_convert_encoding( $word , $target_chrset , $org_charset );
  1302. }
  1303. function qd_detect_order( $param=null ){
  1304. if(is_null($param)){
  1305. return mb_detect_order();
  1306. }else{
  1307. return mb_detect_order( $param );
  1308. }
  1309. }
  1310. //-----------------------------------------
  1311. // Address and Name Keys change Opiton
  1312. //-----------------------------------------
  1313. function addressField( $addr = null , $name = null ){
  1314. if( is_null($addr) && is_null($name) ){
  1315. return array( $this->tokey['_ADDR'] , $this->tokey['_NAME'] );
  1316. }
  1317. if( !is_null($addr) && is_array($addr) && 1 < count($addr) ){
  1318. $_addr = array_shift( $addr ) ;
  1319. $name = array_shift( $addr ) ;
  1320. $addr = $_addr;
  1321. }
  1322. if( (!is_null($addr) && !is_string( $addr )) || !is_null($name) && !is_string($name) ){
  1323. return $this->errorGather('Specify Error in addressField',__LINE__);
  1324. }
  1325. $addr = is_null( $addr ) ? $this->tokey['_ADDR'] : $addr ;
  1326. $name = is_null( $name ) ? $this->tokey['_NAME'] : $name ;
  1327. $this->tokey = array(
  1328. '_ADDR' => $addr,
  1329. '_NAME' => $name,
  1330. );
  1331. return true;
  1332. }
  1333. //-----------------------------------------------------------
  1334. // Wordwrap Opiton
  1335. // array( 'except word' => beginning flag )
  1336. // if beginning flag is true , beginning of a line is target
  1337. // if beginning flag is true , the word in line is target
  1338. //-----------------------------------------------------------
  1339. function wordwrapProhibitConstruct(){
  1340. $ret = $this->strToArrayKey( $this->wrap_prohibit_top , true );
  1341. $ret2 = $this->strToArrayKey( $this->wrap_prohibit_end , false );
  1342. $this->wrap_prohibit = array_merge( $ret , $ret2 );
  1343. }
  1344. function strToArrayKey( $word , $value ){
  1345. $ret = array();
  1346. $enc = $this->qd_detect_encoding( $word );
  1347. $length = mb_strlen( $word , $enc );
  1348. for( $i=0 ; $i < $length ; $i++ ){
  1349. $ret[ mb_substr( $word , $i , 1 , $enc ) ] = $value;
  1350. }
  1351. return $ret;
  1352. }
  1353. function wordwrapAllow( $bool = null ){
  1354. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1355. }
  1356. function wrapProhibitAllow( $bool = null ){
  1357. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1358. }
  1359. function wrapProhibitEnd( $option = null ){
  1360. $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1361. $this->wordwrapProhibitConstruct();
  1362. return $this->errorGather();
  1363. }
  1364. function wrapProhibitTop( $option = null ){
  1365. $this->option( array( __FUNCTION__ => $option ) ,__LINE__);
  1366. $this->wordwrapProhibitConstruct();
  1367. return $this->errorGather();
  1368. }
  1369. function wrapWidth( $bool = null ){
  1370. return $this->option( array( __FUNCTION__ => $bool ) ,__LINE__);
  1371. }
  1372. function wordwrapLength( $length = null ){
  1373. if( is_null( $length ) ){
  1374. return $this->wordwrap_length;
  1375. }
  1376. if( !is_numeric( $length ) || ( is_numeric( $length ) && $length < 1 ) ){
  1377. return $this->errorGather('Wordwrap error , length is illegal' ,__LINE__) ;
  1378. }
  1379. $this->wordwrap_length = $length;
  1380. return $this->errorGather() ;
  1381. }
  1382. function mbStrwidthMagni( $option = null ){
  1383. return $this->option( array( __FUNCTION__ => $option ) ,__LINE__, 0 , 10 );
  1384. }
  1385. function wrapExcept( $array = null ){
  1386. if( null === $array ){
  1387. return $this->wrap_except;
  1388. }
  1389. if( is_string( $array ) || is_numeric( $array ) ){
  1390. $this->wrap_except = array( $array =>false );//default false
  1391. }
  1392. if( is_array( $array ) ){
  1393. if( 0 === count( $array ) ){
  1394. $this->wrap_except = array();
  1395. return $this->errorGather() ;
  1396. }
  1397. foreach( $array as $key => $value){
  1398. if( !is_bool( $value ) ){
  1399. $array[$key] = empty( $value ) ? false:true;
  1400. }else{
  1401. $array[$key] = $value ;
  1402. }
  1403. }
  1404. $this->wrap_except = $array;
  1405. return $this->errorGather() ;
  1406. }
  1407. return $this->errorSpecify(__FUNCTION__,__LINE__);
  1408. }
  1409. //------------------------------------------
  1410. // Charset Option
  1411. //------------------------------------------
  1412. function charsetHeader( $charset = null ){
  1413. if(is_null($charset)){
  1414. return $this->charset_header ;
  1415. }
  1416. $stack = $this->charset();
  1417. $stack['HEADER'] = $charset;
  1418. return $this->charset( $stack );
  1419. }
  1420. function charsetAttach( $charset = null ){
  1421. if(is_null($charset)){
  1422. return $this->charset_attach_filename ;
  1423. }
  1424. $stack = $this->charset();
  1425. $stack['HEADER'] = $charset;
  1426. return $this->charset( $stack );
  1427. }
  1428. function charsetBody( $charset = null , $enc = null ){
  1429. if( is_null($charset) && is_null($enc) ){
  1430. return array($this->charset_content , $this->content_transfer_enc_text , content_transfer_enc_html) ;
  1431. }
  1432. if(is_array($charset)){
  1433. $enc = isset($charset[1]) ? $charset[1]:null;
  1434. $charset = $charset[0];
  1435. }
  1436. $stack = $this->charset();
  1437. if( !is_null($charset) ){
  1438. $stack['BODY'] = $charset;
  1439. }
  1440. if( !is_null($enc) ){
  1441. $stack['HTML'] = $stack['TEXT'] = $enc;
  1442. }
  1443. return $this->charset( $stack );
  1444. }
  1445. function charset( $array = null , $op = null ){
  1446. if( is_null( $array ) && is_null( $op ) ){
  1447. foreach( $this->corres_charset as $key => $value ){
  1448. $ret[$key] = $this->{$value} ;
  1449. }
  1450. return $ret;
  1451. }
  1452. if( !is_null($op) && is_string($op) ){
  1453. $this->content_transfer_enc_text = $op ;
  1454. $this->content_transfer_enc_html = $op ;
  1455. return $this->charset( $array );
  1456. }elseif(!is_null($op) && !is_string($op)){
  1457. return $this->errorSpecify( __FUNCTION__ , __LINE__ );
  1458. }
  1459. if( is_array( $array ) ){
  1460. if( 2===count($array) && isset($array[0]) && isset($array[1])){
  1461. return $this->charset($array[0],$array[1]);
  1462. }
  1463. $array = array_change_key_case( $array , CASE_UPPER );
  1464. foreach( $array as $key => $value ){
  1465. if(isset($this->corres_charset[$key])){
  1466. if( is_string($this->corres_charset[$key]) ){
  1467. $this->{$this->corres_charset[$key]} = $value;
  1468. }else{
  1469. return $this->errorSpecify( __FUNCTION__ , __LINE__ );
  1470. }
  1471. }
  1472. }
  1473. }elseif( is_string($array) ){
  1474. $this->charset_header = $this->charset_content = $this->charset_attach_filename = $array;
  1475. }else{
  1476. return $this->errorSpecify( __FUNCTION__ , __LINE__ );
  1477. }
  1478. return $this->errorGather() ;
  1479. }
  1480. function encoding( $enc = null ){
  1481. if(is_null($enc)){
  1482. return $this->corres_charset['TEXT'];
  1483. }
  1484. $this->corres_charset['TEXT'] = $this->corres_charset['HTML'] = $enc;
  1485. return true;
  1486. }
  1487. //--------------------------
  1488. // set Mutibye Parameter
  1489. //--------------------------
  1490. function setMbParameter( $lang = null , $internal_enc = null , $detect = null ){
  1491. if(is_array($lang)){
  1492. mb_language( $lang[0] ) ;
  1493. mb_internal_encoding( $lang[1] ) ;
  1494. $this->qd_detect_order( $lang[2] );
  1495. }elseif( 'STACK'===strtoupper($lang) ){
  1496. $this->mb_parameter_stack = array(mb_language(),mb_internal_encoding(),$this->qd_detect_order());
  1497. mb_language( $this->lang_def );
  1498. mb_internal_encoding( $this->encoding_def );
  1499. $this->qd_detect_order( $this->detect_def );
  1500. }else{
  1501. if( !is_null( $lang ) ){
  1502. mb_language( $lang ) ;
  1503. }
  1504. if( !is_null( $internal_enc ) ){
  1505. mb_internal_encoding( $internal_enc ) ;
  1506. }
  1507. if( !is_null( $detect ) ){
  1508. $this->qd_detect_order( $detect );
  1509. }
  1510. }
  1511. }
  1512. //--------------------------------
  1513. // Decorationable HTML Mail Opiton
  1514. // ( Inline HTML , MHTML )
  1515. // See $this->deco_def Property
  1516. //--------------------------------
  1517. // Change decoration default along to each career
  1518. function decoDef( $value = null ){
  1519. if( is_null( $value ) ){
  1520. return $this->deco_def_default;
  1521. }
  1522. $this->deco_def_default = $value ;
  1523. return $this->errorGather() ;
  1524. }
  1525. // fix Decoration Pattern by STRING means CareerName
  1526. function decoFix( $cari = null ){
  1527. if(is_null($cari)){
  1528. return $this->deco_kind;
  1529. }
  1530. $this->deco_kind = $this->decoSelect( $cari );
  1531. return true;
  1532. }
  1533. function decoSelect( $deco_kind = null ){
  1534. if( is_null( $deco_kind ) ){
  1535. return $this->deco_def_default;//$this->deco_judge
  1536. }
  1537. $deco_kind = strtoupper( $deco_kind );
  1538. $ret = false ;
  1539. foreach( $this->deco_def as $key => $def ){
  1540. if( in_array( $deco_kind , $def['OPTION_NAME'] ) ){
  1541. $ret = $key ;
  1542. $this->inline_mode = true;
  1543. }
  1544. }
  1545. return $ret;
  1546. }
  1547. // Change Decoration Pattern by E-mail Address
  1548. function decoJudge( $addr_array ){
  1549. $addr=$addr_array[$this->tokey['_ADDR']];
  1550. $start = strrpos( $addr , '@');
  1551. if(empty($start)){
  1552. return $this->deco_def_default;
  1553. }
  1554. $right = trim(substr($addr , $start+1));
  1555. $parts = explode('.',$right);
  1556. $ct = count($parts);
  1557. if( 2 > $ct ){
  1558. return $this->deco_def_default;
  1559. }
  1560. $domains = array();
  1561. $domains[] = $parts[$ct-2] . '.' . $parts[$ct-1];
  1562. if( isset($parts[$ct-3]) ){
  1563. $domains[] = $parts[$ct-3] .'.'.$parts[$ct-2] . '.' . $parts[$ct-1];
  1564. }
  1565. if( isset($parts[$ct-3]) && isset($parts[$ct-4]) ){
  1566. $domains[] = $parts[$ct-4] .'.'. $parts[$ct-3] .'.'.$parts[$ct-2] . '.' . $parts[$ct-1];
  1567. }
  1568. $ct = count($domains);
  1569. $domain = reset($domains);
  1570. while( $ct-- > 0){
  1571. if(isset( $this->deco_judge[$domains[$ct]])){
  1572. $domain = $domains[$ct];
  1573. break;
  1574. }
  1575. }
  1576. return $this->decoSelect(isset( $this->deco_judge[$domain] ) ? $this->deco_judge[$domain]:null);
  1577. }
  1578. //------------------------------------
  1579. //
  1580. // Word Replace
  1581. //
  1582. // You can add prefix by $this->rep_prefix proparty
  1583. // OR $this->repPrefix() Method (Recommended)
  1584. // notice: this functino need on utf-8
  1585. // OR $this->qdmail_system_charset need utf-8
  1586. //------------------------------------
  1587. function replaceWord( $array = null , $add = false ){
  1588. if( is_null( $array ) ){
  1589. return $this->replace ;
  1590. }
  1591. if( !is_array( $array ) ){
  1592. $array = array( $array );
  1593. }
  1594. foreach($array as $key => $arr){
  1595. if( !is_array( $arr ) ){
  1596. $array[$key] = array( $arr );
  1597. }
  1598. }
  1599. if( $add ){
  1600. $this->replace = array_merge( $this->replace , $array );
  1601. }else{
  1602. $this->replace = $array ;
  1603. }
  1604. return $this->errorGather() ;
  1605. }
  1606. function replaceDef( $array = null ){
  1607. if(is_null($array)){
  1608. return $this->replace_def;
  1609. }
  1610. if(is_array($array)){
  1611. $this->replace_def = $array;
  1612. }else{
  1613. return false;
  1614. }
  1615. }
  1616. function repPrefix( $option = null ){
  1617. return $this->stringOption( __FUNCTION__ , $option , __LINE__ );
  1618. }
  1619. function replace( $cont , $rep ){
  1620. foreach($rep as $serch => $replace ){
  1621. if( '_' == mb_substr( $serch , 0 , 1 , $this->qd_detect_encoding($serch) ) ){
  1622. continue;
  1623. }
  1624. if( empty($replace) && !empty($this->replace_def[$serch]) ){
  1625. $replace = $this->replace_def[$serch];
  1626. }
  1627. $reg = '/%' . $this->rep_prefix . (string) $serch . '%/is' ;
  1628. $cont = $this->qdmail_preg_replace( $reg , $replace , $cont );
  1629. }
  1630. return $cont;
  1631. }
  1632. function qdmail_preg_replace( $reg , $rep , $cont ){
  1633. $enc = $this->qd_detect_encoding( $cont );
  1634. $_reg = $this->qd_convert_encoding( $reg , $this->qdmail_system_charset , $this->qd_detect_encoding( $reg ) );
  1635. $_rep = $this->qd_convert_encoding( $rep , $this->qdmail_system_charset , $this->qd_detect_encoding( $rep ) );
  1636. $_cont = $this->qd_convert_encoding( $cont , $this->qdmail_system_charset , $enc );
  1637. $cont = preg_replace( $_reg , $_rep , $_cont );
  1638. return $this->qd_convert_encoding($cont , $enc , $this->qdmail_system_charset );
  1639. }
  1640. //------------------------------------
  1641. // OOP User Interface (Recommended)
  1642. //------------------------------------
  1643. function to( $addr = null , $name = null , $add = false ){
  1644. return $this->addrs( 'TO' , $addr , $name , $add );
  1645. }
  1646. function cc( $addr = null , $name = null , $add = false ){
  1647. return $this->addrs( 'CC' , $addr , $name , $add );
  1648. }
  1649. function bcc( $addr = null , $name = null , $add = false ){
  1650. return $this->addrs( 'BCC' , $addr , $name , $add );
  1651. }
  1652. function from( $addr = null , $name = null ){
  1653. return $this->addrs( 'FROM' , $addr , $name , false );
  1654. }
  1655. function replyto( $addr = null , $name = null ){
  1656. return $this->addrs( 'REPLYTO' , $addr , $name , false );
  1657. }
  1658. function addHeader( $header_name = null , $value = null){
  1659. if('REPLY-TO'==strtoupper($header_name)){
  1660. $header_name = 'REPLYTO' ;
  1661. }
  1662. if(isset($this->addr_head_name[strtoupper($header_name)])){
  1663. return $this->{strtolower($header_name)}( $value , null , true );
  1664. } if(is_null($header_name)){
  1665. return $this->other_header;
  1666. }
  1667. if('clear'===strtolower($header_name) && is_null($value)){
  1668. $this->other_header=array();
  1669. return ;
  1670. }
  1671. $this->other_header[$header_name] = $value ;
  1672. }
  1673. function reset( $debugErase = false ){
  1674. if( !$debugErase ){
  1675. $stack_debug = $this->debug ;
  1676. }
  1677. $stack = $this->stack_construct;
  1678. $array = get_class_vars( $this->name ) ;
  1679. foreach($array as $key => $value){
  1680. $this->{$key} = $value ;
  1681. }
  1682. $this->__construct( $stack );
  1683. if( !$debugErase ){
  1684. $this->debug = $stack_debug ;
  1685. }
  1686. }
  1687. function resetHeader(){
  1688. $this->to = array();
  1689. $this->cc = array();
  1690. $this->bcc = array();
  1691. $this->from = array();
  1692. $this->replyto = array();
  1693. $this->other_header=array();
  1694. $this->subject = null;
  1695. }
  1696. function resetBody(){
  1697. $this->body('');
  1698. $this->is_html = null;
  1699. $this->deco_kind = null;
  1700. $this->inline_mode = false;
  1701. $this->attach = array();
  1702. }
  1703. function resetHeaderBody(){
  1704. $this->resetBody();
  1705. $this->resetHeader();
  1706. }
  1707. function _gatherFromArray( $array , $key ){
  1708. $ret = array();
  1709. foreach( $array as $ar ){
  1710. $ret[] = $ar[$key] ;
  1711. }
  1712. return $ret;
  1713. }
  1714. function done(){
  1715. return $this->_gatherFromArray( $this->done , $this->tokey['_ADDR'] );
  1716. }
  1717. function undone(){
  1718. return $this->_gatherFromArray( $this->undone , $this->tokey['_ADDR'] );
  1719. }
  1720. function subject( $subj = null ){
  1721. if( is_null($subj) ){
  1722. return $this->subject;
  1723. }
  1724. if( is_string( $subj ) || is_numeric( $subj ) ){
  1725. $this->subject['CONTENT'] = (string) $subj;
  1726. return $this->errorGather() ;
  1727. }elseif( is_array($subj) ){
  1728. $subj = array_change_key_case( $subj , CASE_UPPER );
  1729. if(isset($subj['CONTENT'])){
  1730. $this->subject = $subj;
  1731. }else{
  1732. $this->subject['CONTENT'] = (string) $subj[0];
  1733. $this->subject['_CHARSET'] = isset($subj[1]) ? $subj[1] : null ;
  1734. $this->subject['_ORG_CHARSET'] = isset($subj[2]) ? $subj[2] : null ;
  1735. }
  1736. return $this->errorGather() ;
  1737. }else{
  1738. return $this->errorSpecify(__FUNCTION__,__LINE__);
  1739. }
  1740. }
  1741. function body( $type =null , $cont = null , $length = null , $charset = null , $enc = null , $org_charset = null ){
  1742. if(is_null($type)){
  1743. return $this->content;
  1744. }
  1745. if(empty($type)){
  1746. $this->content = array(
  1747. 'TEXT'=>array(
  1748. 'CONTENT' => null,
  1749. 'LENGTH' => null,
  1750. '_CHARSET' => null,
  1751. 'ENC' => null,
  1752. '_ORG_CHARSET' => null,
  1753. ),
  1754. 'HTML'=>array(
  1755. 'CONTENT' => null,
  1756. 'ORG_CONTENT' => null,
  1757. 'LENGTH' => null,
  1758. '_CHARSET' => null,
  1759. 'ENC' => null,
  1760. '_ORG_CHARSET' => null,
  1761. ),
  1762. );
  1763. return true;
  1764. }
  1765. $type = strtolower( $type );
  1766. if( 'text'!==$type && 'html'!==$type ){
  1767. return $this->errorGather('You must use \'text\' or \'html\'' ,__LINE__) ;
  1768. }
  1769. if( is_array( $cont ) ){
  1770. $def = array(
  1771. 'CONTENT'=>null,
  1772. 'LENGTH'=>null,
  1773. '_CHARSET'=>null,
  1774. 'ENC'=>null,
  1775. '_ORG_CHARSET'=>null,
  1776. );
  1777. $temp = array_change_key_case( array_merge($def,$cont) , CASE_UPPER);
  1778. }else{
  1779. $temp = array(
  1780. 'CONTENT'=>$cont,
  1781. 'LENGTH'=>$length,
  1782. '_CHARSET'=>$charset,
  1783. 'ENC'=>$enc,
  1784. '_ORG_CHARSET'=>$org_charset,
  1785. );
  1786. }
  1787. $this->content[strtoupper($type)] = array_merge( $this->content[strtoupper($type)] , $temp );
  1788. return $this->errorGather() ;
  1789. }
  1790. function text( $cont , $length = null , $charset = null , $enc = null , $org_charset = null ){
  1791. return $this->body('text', $cont , $length , $charset , $enc , $org_charset );
  1792. }
  1793. function html( $cont , $charset = null , $enc = null , $org_charset = null ){
  1794. return $this->body('html', $cont , null , $charset , $enc , $org_charset );
  1795. }
  1796. //--------------------------
  1797. // assist User Interface
  1798. //--------------------------
  1799. function addrs( $section , $addr = null , $name = null , $add = false ){
  1800. $section = strtolower( $section );
  1801. $ck = array('to'=>true,'from'=>true,'cc'=>true,'bcc'=>true,'replyto'=>true);
  1802. if(empty($ck[$section])){
  1803. return $this->errorGather('Illegal Section Name \''.$section.'\'' ,__LINE__) ;
  1804. }
  1805. if( is_null( $addr ) && is_null( $name )){
  1806. return $this->{$section} ;
  1807. }
  1808. if( false === $addr ){
  1809. $this->{$section} = array();
  1810. return $this->errorGather() ;
  1811. }
  1812. $addr = $this->analyzeAddr( $addr , $name );
  1813. if( !$this->allow_blank_header && empty($addr[0][$this->tokey['_ADDR']]) ){// if addres is empty , no set
  1814. return true;
  1815. }
  1816. if( !$add ){
  1817. $this->{$section} = $addr;
  1818. }else{
  1819. $this->{$section} = array_merge( $this->{$section} , $addr );
  1820. }
  1821. return ( 0 != count( $addr ) );
  1822. }
  1823. function analyzeAddr( $addr , $name ){
  1824. if( is_string( $addr ) ){
  1825. if( empty( $name ) ){
  1826. list( $name , $addr ) = $this->_extractNameAddr( $addr );
  1827. }else{
  1828. $addr = $this->extractAddr( $addr );
  1829. }
  1830. return array(array( $this->tokey['_ADDR'] => $addr , $this->tokey['_NAME'] => $name ));
  1831. }
  1832. // $addr is array
  1833. ## list( $addr , $void ) = $this->keyUpper( $addr );
  1834. $ret = array();
  1835. if( empty( $name ) || !is_array( $name ) ){
  1836. if(isset($addr[$this->tokey['_ADDR']])){
  1837. $addr[$this->tokey['_NAME']] = isset($addr[$this->tokey['_NAME']]) ? $addr[$this->tokey['_NAME']]:null;
  1838. return array( $addr );//ver 0.7.3a
  1839. }elseif( isset( $addr[0] ) && is_array( $addr[0] ) ){
  1840. foreach($addr as $ad){
  1841. ## list( $ad , $void ) = $this->keyUpper( $ad );
  1842. $_addr = isset( $ad[$this->tokey['_ADDR']] ) ? $this->extractAddr( $ad[$this->tokey['_ADDR']] ) : $this->extractAddr( $ad[0] ) ;
  1843. if(isset( $ad[$this->tokey['_NAME']] ) ){
  1844. $_name = $ad[$this->tokey['_NAME']];
  1845. }elseif( isset( $ad[1] ) ){
  1846. $_name = $ad[1];
  1847. }else{
  1848. $_name = null;
  1849. }
  1850. if( empty($_addr) ){
  1851. continue;
  1852. }else{
  1853. $ret[] = array_merge( $ad , array( $this->tokey['_ADDR'] => $_addr , $this->tokey['_NAME'] => $_name ) );
  1854. }
  1855. }
  1856. return $ret;
  1857. }else{
  1858. $_addr = $this->extractAddr( $addr[0] );
  1859. $_name = isset($addr[1]) ? $addr[1]:null;
  1860. $ret[] = array($this->tokey['_ADDR'] => $_addr , $this->tokey['_NAME'] => $_name);
  1861. }
  1862. return $ret; //fool proof
  1863. }else{
  1864. foreach( $addr as $key => $value ){
  1865. $_addr = $this->extractAddr( $value );
  1866. $_name = $name[$key] ;
  1867. if( empty( $_addr ) ){
  1868. continue;
  1869. }else{
  1870. $ret[] = array( $this->tokey['_ADDR'] => $_addr , $this->tokey['_NAME'] => $_name );
  1871. }
  1872. }
  1873. return $ret;
  1874. }
  1875. return $ret; // fool proof
  1876. }
  1877. //--------------------------------------------------------
  1878. // From MutibyteName<example@example.com> To MutibyteName
  1879. //--------------------------------------------------------
  1880. function _extractNameAddr( $addr ){
  1881. $formed_addr = $this->extractAddr( $addr );
  1882. if( empty( $formed_addr ) ){
  1883. return false;
  1884. }
  1885. $addr = trim($addr);
  1886. $addr = str_replace(array('<','>'),'',$addr);
  1887. $temp=strpos($addr,$formed_addr);
  1888. if( false === $temp ){
  1889. return null;
  1890. }
  1891. return array( substr( $addr , 0 , strpos( $addr , $formed_addr )) , $formed_addr );
  1892. }
  1893. function setContentArgs( $type , $param ){
  1894. $method_name = 'text';
  1895. if('HTML' == $type ){
  1896. $method_name = 'html';
  1897. }
  1898. $cont = null;
  1899. if(isset($param[$type])){
  1900. $cont = $param[$type];
  1901. }elseif(isset($param['CONTENT'])){
  1902. $cont = $param['CONTENT'];
  1903. }
  1904. return $this->{$method_name}(
  1905. $cont ,
  1906. isset($param['_CHARSET']) ? $param['_CHARSET']:null,
  1907. isset($param['ENC']) ? $param['ENC']:null,
  1908. isset($param['_ORG_CHARSET']) ? $param['_ORG_CHARSET']:null
  1909. );
  1910. }
  1911. //-------------------------------------------
  1912. // Main Routine Send()
  1913. // Option analyize
  1914. // Is To-Separate Mode ?
  1915. // loop:sendbase
  1916. // Already Created Mail?
  1917. // Create mail
  1918. // Additional Parameter(From User) Analyize (e.g. charset , subject etc...)
  1919. // (Not OOP MODE)
  1920. // Build Header(except Content-type etc) and Must Header Checking
  1921. // Both mode ? text only or html only or both ? or auto both
  1922. // Addition Attachment will do
  1923. // Select Body Structure by Decoration Pattern or else
  1924. // Build Body ( Recursive )
  1925. // Render Body with 'Content-type' Header and Boundary etc..
  1926. // + finalize( Recursive )
  1927. // Pass to the Header,first Content-type etc. that needs by Header Render Routine
  1928. // Set Default Header, MIME 1.0 etc
  1929. // Render Header and Render for SMTP Sender Text(Future)
  1930. // Debug Echo & log & error log will do if you want
  1931. //If error exsist , no sender(except ignore_error Property)
  1932. //-------------------------------------------
  1933. function headerDefault(){
  1934. $this->header['MIME-Version'] = '1.0';
  1935. if($this->debug > 0 ){
  1936. $this->header['X-QdmailDebug'] = trim(chunk_split ( base64_encode($this->iniGather()) , $this->mime_encode_max , $this->LFC."\t" ));
  1937. }
  1938. $this->header['X-'.$this->xmailer] = trim('version-'.$this->version . ' ' . $this->license .' http://hal456.net/qdmail PHPver '.PHP_VERSION);
  1939. if($this->smtp){
  1940. $sendby = 'SMTP';
  1941. }elseif($this->sendmail && !ini_get('SafeMode')){
  1942. $sendby = 'Sendmail';
  1943. }elseif($this->sendmail && ini_get('SafeMode')){
  1944. $sendby = 'MailFunction but Sendmail if no Safemode';
  1945. }else{
  1946. $sendby = 'MailFunction';
  1947. }
  1948. $this->header['X-'.$this->xmailer] .= $this->LFC . chr(9) . 'send-by '.$sendby;
  1949. }
  1950. function makeMessageId(){
  1951. $req_uri = empty($_SERVER['REQUEST_URI']) ? '':$_SERVER['REQUEST_URI'];
  1952. if(is_null($this->message_id_right)){
  1953. $right = 'hal456.net';
  1954. }else{
  1955. $right = $this->message_id_right;
  1956. }
  1957. $id = 'Qdmail.' . $this->version
  1958. . '_' . sha1( microtime() . $this->salt . mt_rand() . $req_uri )
  1959. . '@' . $right ;
  1960. return '<'.$id.'>';
  1961. }
  1962. function send( $option = null ){
  1963. if( is_null( $this->start_time )){
  1964. $this->start_time = microtime();
  1965. }
  1966. // mb language
  1967. if( 'neutral' === mb_language() ){
  1968. $this->setMbParameter('stack');
  1969. }
  1970. if( is_object( $option ) ){
  1971. $this->smtp_object = & $option;
  1972. $this->smtp = true;
  1973. $option = null ;
  1974. }
  1975. // Date: header
  1976. if( !is_null($this->time_zone) ){
  1977. $other = array_change_key_case($this->other_header,CASE_UPPER);
  1978. if( !isset($other['DATE']) ){
  1979. $this->other_header['Date'] = date('D, d M Y h:i:s ') . $this->time_zone;
  1980. }
  1981. }
  1982. $fg = true;
  1983. if( true === $this->toSeparate() ){
  1984. $stack_tos = array( $this->to , $this->cc , $this->bcc );
  1985. $tos = $this->to ;
  1986. # $this->cc( false ) ;
  1987. # $this->bcc( false ) ;
  1988. if( empty( $tos ) ){
  1989. $fg = $this->errorGather('recipient Header is not exsit line' ,__LINE__) ;
  1990. }else{
  1991. // To Separate mode
  1992. foreach($tos as $key => $to){
  1993. if( $this->simple_replace ){
  1994. if($this->replace_with_to_priority){
  1995. $to = array_merge( $this->selectReplace( $to , $key ) ,$to );
  1996. }else{
  1997. $to = array_merge( $to , $this->selectReplace( $to , $key ) );
  1998. }
  1999. }
  2000. $this->to( $to , null , false );
  2001. $this->debugEchoLf($this->to);
  2002. if( $this->auto_deco_judge ){
  2003. $this->deco_kind = $this->decoJudge( $this->to[0] );
  2004. }
  2005. if( $this->sendBase() ){
  2006. $this->is_create = false; // for next to
  2007. continue ;
  2008. }else{
  2009. $this->is_create = false; // for next to
  2010. $fg = $this->errorGather('Error \'TO\' Separate mode in Sendbase function , the Address is -> '.$this->to[0][$this->tokey['_ADDR']] ,__LINE__) ;
  2011. }
  2012. }
  2013. }
  2014. list( $this->to , $this->cc , $this->bcc ) = $stack_tos ;
  2015. }else{
  2016. // normal mode the end
  2017. $fg = $this->sendBase() ;
  2018. $this->is_create = false;
  2019. }
  2020. $this->setMbParameter($this->mb_parameter_stack);
  2021. $this->log();
  2022. //debug
  2023. $this->debugEcho('END');
  2024. if( $fg ){
  2025. return $this->errorGather();
  2026. }else{
  2027. return $this->errorGather('Send Error' ,__LINE__) ;
  2028. }
  2029. }
  2030. function selectReplace( $to , $key ){
  2031. $ret = array();
  2032. if( isset( $this->replace[$to[$this->tokey['_ADDR']]] ) ){
  2033. $ret = $this->replace[$to[$this->tokey['_ADDR']]];
  2034. }elseif( isset( $this->replace[$key] ) ){
  2035. $ret = $this->replace[$key];
  2036. }
  2037. return $ret ;
  2038. }
  2039. function sendBase(){
  2040. // stack bcc for allways bcc
  2041. unset( $stack_bcc ) ;
  2042. if( 0 != count( $this->allways_bcc ) ){
  2043. $stack_bcc = $this->bcc ;
  2044. $this->bcc( $this->allways_bcc , null , true );
  2045. }
  2046. // Message Id
  2047. if( $this->message_id){
  2048. $other = array_change_key_case($this->other_header,CASE_UPPER);
  2049. if(!isset($other['MESSAGE-ID'])){
  2050. $this->other_header['Message-Id'] = $this->makeMessageId();
  2051. }
  2052. }
  2053. if( !$this->is_create ){
  2054. $this->body = null;
  2055. $this->after_id = null;
  2056. $this->createMail();
  2057. }
  2058. if( isset($option) && !empty($option) ){
  2059. list( $option , $void ) = $this->keyUpper( $option );
  2060. }
  2061. // for smtp and sendmail
  2062. $this->extractrecipient() ;
  2063. $fg = true;
  2064. $fg_debug = ( 2 > $this->debug ) && !$this->render_mode;
  2065. if( $fg_debug && ( ( 0 === count( $this->error ) ) && ( 0 === count( $this->error_stack ) ) ) || $this->ignore_error ) {
  2066. //
  2067. // mail or SMTP or sendmail
  2068. //
  2069. if( $this->smtp ){
  2070. $fg = $this->sendBySmtp();
  2071. }elseif( $this->sendmail && !ini_get('safe_mode') ){
  2072. $fg = $this->sendBySendmail();
  2073. }elseif( ini_get('safe_mode') ){
  2074. $fg = mail(
  2075. trim( $this->header_for_mailfunction_to )
  2076. , trim( $this->header_for_mailfunction_subject )
  2077. , $this->content_for_mailfunction
  2078. , trim( $this->header_for_mailfunction_other )
  2079. );
  2080. }else{
  2081. $fg = mail(
  2082. trim( $this->header_for_mailfunction_to )
  2083. , trim( $this->header_for_mailfunction_subject )
  2084. , $this->content_for_mailfunction
  2085. , trim( $this->header_for_mailfunction_other )
  2086. , trim( $this->mta_option )
  2087. );
  2088. }
  2089. if( $fg ){
  2090. $this->done = array_merge( $this->done , $this->to , $this->cc , $this->bcc ) ;
  2091. }else{
  2092. $this->undone = array_merge( $this->undone , $this->to , $this->cc , $this->bcc ) ;
  2093. $err_mes = $this->smtp ? 'SMTP mail method':'PHP mail function';
  2094. $err_mes = $this->sendmail ? 'sendmail of localhost':$err_mes;
  2095. $fg =$this->errorGather('No send . Because '.$err_mes.' replied error' ,__LINE__);
  2096. }
  2097. }elseif( $fg_debug ){
  2098. $this->undone = array_merge( $this->undone , $this->to , $this->cc , $this->bcc ) ;
  2099. $fg = $this->errorGather('Error happen, see upper' ,__LINE__);;
  2100. }else{
  2101. $this->undone = array_merge( $this->undone , $this->to , $this->cc , $this->bcc ) ;
  2102. $fg = true ;
  2103. }
  2104. //debug
  2105. $bcc = null;
  2106. if( !empty($this->header_for_smtp_bcc )){
  2107. $bcc = '('.$this->header_for_smtp_bcc.')';
  2108. }
  2109. $this->debugEchoLf(
  2110. $bcc ,
  2111. $this->content_all_for_smtp,
  2112. // $this->header_for_smtp,
  2113. // $this->content_for_mailfunction,
  2114. $this->LFC.$this->LFC ,
  2115. date('Y-m-d H:i:s')
  2116. );
  2117. if($this->debug_report){
  2118. $this->debugReport('FILE');
  2119. }
  2120. if( isset( $stack_bcc ) ){
  2121. $this->bcc = $stack_bcc ;
  2122. }
  2123. return $this->errorGather() && $fg;
  2124. }
  2125. //-----------------
  2126. // checking
  2127. //-----------------
  2128. function mustCheck(){
  2129. if( 0 == count( $this->header_must ) ){
  2130. return $this->errorGather() ;
  2131. }
  2132. $must = true;
  2133. foreach( $this->header_must as $hdn ){
  2134. $header_upp = array_change_key_case( $this->header , CASE_UPPER );
  2135. if( ( !$this->smtp && empty( $header_upp[strtoupper($hdn)] ) ) || ( $this->smtp && empty( $header_upp[strtoupper($hdn)] ) && !isset( $this->smtp_server['FROM'] ) ) ){
  2136. $must = $this->errorGather('Must Header is not exist \''.$hdn.'\'' ,__LINE__) ;
  2137. }
  2138. }
  2139. return $must;
  2140. }
  2141. //-----------------------------------------------
  2142. // Create one mail
  2143. //-----------------------------------------------
  2144. function createMail( $boundary = null , $boundary_fix = false){
  2145. $this->_charsetDefFix();
  2146. //
  2147. // content(body) force convert to utf-8 ,
  2148. // because some system function can't do collectlly whitout utf-8,ex preg_replace,striptags
  2149. //
  2150. $this->content = $this->convertCharsetRecursive( $this->content , $this->qdmail_system_charset );
  2151. $this->buildHeader();
  2152. if(!$this->mustCheck()){
  2153. return false;
  2154. };
  2155. // Text only or Html Only or both ?
  2156. if( empty( $this->is_html ) ){
  2157. if( $this->issetContent( $this->content['HTML'] ) && $this->issetContent( $this->content['TEXT'] ) ){
  2158. $this->is_html = 'BOTH' ;
  2159. }elseif( $this->issetContent( $this->content['HTML'] ) && $this->auto_both ){
  2160. $this->content['TEXT'] = array(
  2161. 'content'=>$this->htmlToText( $this->content['HTML']['CONTENT'] )
  2162. );
  2163. $this->is_html = 'BOTH';
  2164. }elseif( $this->issetContent( $this->content['HTML'] ) && !$this->auto_both ){
  2165. $this->is_html = 'HTML';
  2166. }else{
  2167. $this->is_html = 'TEXT';
  2168. }
  2169. }
  2170. // Select Body Structure
  2171. if( !isset( $this->deco_kind ) ){
  2172. $structure_no = 0 ;
  2173. }else{
  2174. $structure_no = $this->deco_def[$this->deco_kind]['STRUCTURE'];
  2175. }
  2176. // Short cut on many recipients , samebody
  2177. if( !$this->body_build_once && $this->attach_build_once && $this->attach_already_build){
  2178. //only text and html making
  2179. $this->replaceBodyStructure('TEXT');
  2180. $this->replaceBodyStructure('HTML');
  2181. }elseif(
  2182. ($this->body_build_once && !$this->body_already_build)
  2183. ||
  2184. ( !$this->body_build_once && ( !$this->attach_build_once || ( $this->attach_build_once && !$this->attach_already_build ) ) )
  2185. ){
  2186. $this->body_structure = $this->buildBody( $this->structure[$structure_no] ,$boundary, false , $boundary_fix );
  2187. }
  2188. if( !$this->body_build_once || ($this->body_build_once && !$this->body_already_build) ){
  2189. $this->renderBody();//including Content-type Header
  2190. }
  2191. $this->header = array_merge($this->header , $this->header_content_type);
  2192. // user added header
  2193. $this->headerDefault();
  2194. $this->renderHeader();
  2195. //
  2196. // signed
  2197. //
  2198. if( false===$this->sign ){
  2199. $this->content_all_for_smtp = $this->header_for_smtp . $this->LFC . $this->content_for_mailfunction;
  2200. }elseif($this->pgp){
  2201. // future PGP
  2202. }else{
  2203. // S/MIME
  2204. $this->content_all_for_smtp = $this->signSmime();
  2205. if(false===$this->content_all_for_smtp){
  2206. return $this->errorGather('Sign Error S/MIME',__LINE__);
  2207. }
  2208. }
  2209. $this->is_create=true;
  2210. }
  2211. function signSmime(){
  2212. if( !$this->smtp ){
  2213. return $this->errorGather('S/MIME needs SMTP Send,now You spcify no smtp',__LINE__);
  2214. }
  2215. // Path to certificate file , by Win or other OS
  2216. if(empty($this->certificate_file_path)){
  2217. $this->certificate_file_path = $this->isWin() ? $this->certificate_file_path_win : $this->certificate_file_path_unix;
  2218. }
  2219. if(empty($this->certificate_temp_path)){
  2220. $this->certificate_file_path = $this->isWin() ? $this->certificate_file_path_win : $this->certificate_file_path_unix;
  2221. }
  2222. $path = $this->certificate_file_path . QD_DS ;
  2223. if('PFX'===strtoupper(substr($this->certificate_file,-3))){
  2224. if(!function_exists('openssl_pkcs12_read')){
  2225. return $this->errorGather('You can not specify *.pfx type, please *.pem type becuase your PHP Version do not support \'openssl_pkcs12_read\'',__LINE__);
  2226. }
  2227. if(openssl_pkcs12_read(file_get_contents($path.$this->certificate_file),$ret,$this->certificate_pass)){
  2228. $private_key = $ret['pkey'];
  2229. $certificate = $ret['cert'];
  2230. }else{
  2231. return $this->errorGather('Illegal Certificate File \''.$path.$this->certificate_file.'\' or Incorrect Password ',__LINE__);
  2232. }
  2233. }else{
  2234. $private_key = file_get_contents( $path . $this->private_key_file );
  2235. $certificate = file_get_contents( $path . $this->certificate_file );
  2236. }
  2237. $temp = sha1($this->content_for_mailfunction).'.txt';
  2238. $temp_filename = $this->certificate_temp_path.QD_DS.'temp'.$temp;
  2239. $temp_signed_filename = $this->certificate_temp_path.QD_DS.'temp_signed'.$temp;
  2240. $fp = fopen( $temp_filename , "w" );
  2241. fputs( $fp , $this->content_for_mailfunction . $this->LFC );
  2242. fclose($fp);
  2243. unset($this->header_for_smtp_array['MIME-Version']);
  2244. openssl_pkcs7_sign(
  2245. $temp_filename,
  2246. $temp_signed_filename,
  2247. $certificate,
  2248. array($private_key, $this->certificate_pass),
  2249. $this->header_for_smtp_array
  2250. );
  2251. $ret = file_get_contents($temp_signed_filename);
  2252. unlink ( $temp_signed_filename );
  2253. unlink ( $temp_filename );
  2254. return $ret;
  2255. }
  2256. function replaceBodyStructure( $kind ){
  2257. $content_type = ( 'TEXT' === $kind ) ? 'text/plain':'text/html';
  2258. $false = false;
  2259. $rep = & $this->serchBodyStructure( $content_type , $this->body_structure , $false );
  2260. if( false === $rep ){
  2261. return false;
  2262. }
  2263. list( $content , $charset , $enc ) = $this->makeContentText( $this->content[$kind] , $kind );
  2264. $rep['CONTENT'] = $content;
  2265. $rep['HEADER']['Content-Type'] = $content_type.'; charset="' . $charset . '"';
  2266. $rep['HEADER']['Content-Transfer-Encoding'] = $enc ;
  2267. }
  2268. function & serchBodyStructure( $content_type , & $bbs , & $false ){
  2269. foreach($bbs as $fkey => $bs){
  2270. if( isset( $bs['HEADER']) && ( 0 < count($bs['HEADER']))) {
  2271. $len = strlen($content_type);
  2272. foreach( $bs['HEADER'] as $key => $cont ){
  2273. if( ('CONTENT-TYPE' === strtoupper($key)) && ($content_type === substr($cont,0,$len)) ){
  2274. return $bbs[$fkey];
  2275. }
  2276. }
  2277. }
  2278. if( !isset( $bs['CONTENT']) || ( isset( $bs['CONTENT']) && !is_array( $bs['CONTENT']))){
  2279. continue;
  2280. }
  2281. $ret = & $this->serchBodyStructure( $content_type , $bbs[$fkey]['CONTENT'] , $false );
  2282. return $ret;
  2283. }
  2284. return $false;
  2285. }
  2286. //except Content-type,user option
  2287. function buildHeader(){
  2288. $header = array();
  2289. foreach( $this->addr_many as $section => $many ){
  2290. if( 0 == count( $this->{strtolower( $section )} ) ){
  2291. continue;
  2292. }
  2293. foreach( $this->{strtolower($section)} as $one ){
  2294. $mime=$this->mimeEncode(
  2295. $one[$this->tokey['_NAME']],
  2296. isset($one['_CHARSET']) ? $one['_CHARSET'] : $this->charset_header,
  2297. isset($one['_ORG_CHARSET']) ? $one['_ORG_CHARSET'] : null,
  2298. strlen($section)+2
  2299. );
  2300. // bcc header is not allowed MimeName
  2301. if( empty( $mime ) || 'BCC'===strtoupper( $section ) ){
  2302. $header[$this->addr_head_name[$section]][] = $one[$this->tokey['_ADDR']];
  2303. }else{
  2304. $header[$this->addr_head_name[$section]][] = $mime.' <'.$one[$this->tokey['_ADDR']].'>';
  2305. }
  2306. }
  2307. if( !$many ){
  2308. $header[$this->addr_head_name[$section]] = array( array_pop( $header[$this->addr_head_name[$section]] ) );
  2309. }
  2310. }
  2311. if( !empty( $this->subject ) ){
  2312. //replace
  2313. if( $this->simple_replace ){
  2314. $subj = $this->replace( $this->subject['CONTENT'] , $this->to[0] );
  2315. }else{
  2316. $subj = $this->subject['CONTENT'] ;
  2317. }
  2318. $header['Subject']=$this->mimeEncode(
  2319. $subj ,
  2320. isset($this->subject['_CHARSET']) ? $this->subject['_CHARSET']:$this->charset_header,
  2321. isset($this->subject['_ORG_CHARSET']) ? $this->subject['_ORG_CHARSET'] : null,
  2322. 9 //strlen(subject)+2
  2323. );
  2324. }
  2325. $this->header = array_merge( $header , $this->other_header ) ;
  2326. }
  2327. function renderHeader(){
  2328. if(isset($this->header['To'])){
  2329. $this->header_for_mailfunction_to = implode( ','.$this->LFC.' ' , $this->header['To'] );
  2330. unset( $this->header['To'] ) ;
  2331. }
  2332. if(isset($this->header['Subject'])){
  2333. $this->header_for_mailfunction_subject = $this->header['Subject'];
  2334. unset( $this->header['Subject'] ) ;
  2335. }
  2336. $this->header_for_mailfunction_other = null;
  2337. $header_for_smtp = array();
  2338. $this->header_for_smtp_bcc = null;
  2339. $header_for_smtp['To'] = $this->header_for_mailfunction_to;
  2340. $header_for_smtp['Subject'] = $this->header_for_mailfunction_subject;
  2341. foreach( $this->header as $key => $value ){
  2342. if( is_array( $value ) ){
  2343. $add = implode( ',' . $this->LFC . chr(9) , $value );
  2344. }else{
  2345. $add = $value;
  2346. }
  2347. if( 'BCC' !== strtoupper($key) ){
  2348. $header_for_smtp[$key] = $add ;
  2349. }else{
  2350. $this->header_for_smtp_bcc = $key . ': ' . $add . $this->LFC ;
  2351. }
  2352. $this->header_for_mailfunction_other .= $key . ': ' . $add . $this->LFC;
  2353. unset( $this->header[$key] );
  2354. }
  2355. $this->header_for_smtp = '';
  2356. foreach($header_for_smtp as $key => $value){
  2357. $this->header_for_smtp .= $key.': '.$value.$this->LFC;
  2358. }
  2359. if($this->smime){
  2360. $this->header_for_smtp_array = $header_for_smtp;
  2361. }
  2362. }
  2363. //-------------------------
  2364. // $ret = array(
  2365. // 'BOUNDARY' =>
  2366. // 'HEADER' =>
  2367. // 'CONTENT' =>array(
  2368. // (Recursive)
  2369. // )
  2370. // )
  2371. //-------------------------
  2372. function isInlineImage($filename){
  2373. if(!empty($this->content['HTML']['ORG_CONTENT'])){
  2374. $cont = $this->content['HTML']['ORG_CONTENT'];
  2375. }
  2376. if(!empty($this->content['HTML']['CONTENT'])){
  2377. $cont = $this->content['HTML']['CONTENT'];
  2378. }
  2379. if(empty($cont)){
  2380. return false;
  2381. }
  2382. $enc = $this->qd_detect_encoding($cont);
  2383. $cont = $this->qd_convert_encoding($cont,'UTF-8',$enc);
  2384. $name = $filename;
  2385. $enc = $this->qd_detect_encoding($name);
  2386. $name = $this->qd_convert_encoding($filename,'utf-8',$enc);
  2387. if( 0 < preg_match('/"cid:'.$name.'"/is' , $cont ) ){
  2388. return true;
  2389. }else{
  2390. return false;
  2391. };
  2392. }
  2393. function buildBody( $structure , $boundary = null , $rel = false , $boundary_fix = false){
  2394. $ret = array();
  2395. $one = array();
  2396. if( is_null( $boundary ) ){
  2397. $boundary = $this->makeBoundary();
  2398. }
  2399. $ret_boundary = $boundary ;
  2400. foreach($this->attach as $key => $att){
  2401. if($this->isInlineImage(basename($this->attach[$key]['PATH'])) && empty($this->attach[$key]['CONTENT-ID'])){
  2402. $this->attach[$key]['CONTENT-ID'] = basename($this->attach[$key]['PATH']);
  2403. }
  2404. }
  2405. foreach( $structure as $key => $value ){
  2406. $ret_header = array();
  2407. $ret_cont = array();
  2408. if( is_array( $value ) ){
  2409. $next_boundary = $boundary_fix ? $boundary:$this->makeBoundary();
  2410. $ret_header['Content-Type'] = strtolower($key).';' . $this->LFC
  2411. . ' boundary="' . $next_boundary . '"' ;
  2412. $rel = false;
  2413. $ret_cont = $this->buildBody( $value , $next_boundary , $rel);
  2414. if( 0 == count($ret_cont) && $structure['OMIT']){
  2415. continue;
  2416. }elseif( 1 == count($ret_cont) && $structure['OMIT']){
  2417. $one = null;
  2418. $ret_cont[0]['BOUNDARY'] = '--'.$boundary ;
  2419. $ret[] = $ret_cont[0];
  2420. continue;
  2421. }else{
  2422. $one = null;
  2423. $ret_cont[] = array( 'BOUNDARY' => null ,'HEADER' => array() ,'CONTENT' => '--' . $next_boundary . '--' );
  2424. $ret[] = array( 'BOUNDARY' => '--' . $ret_boundary , 'HEADER' => $ret_header , 'CONTENT' => $ret_cont );
  2425. continue;
  2426. }
  2427. }else{
  2428. switch( strtolower($key) ){
  2429. case 'image':
  2430. foreach( $this->attach as $att){
  2431. if( ( 'INLINE' === $value ) && $this->isSetCid( $att ) ){
  2432. $ret_cont[]= $this->buildAttach( $att , $boundary , true ) ;
  2433. }elseif( ( 'NOT_INLINE' === $value ) && !$this->isSetCid( $att )){
  2434. $ret_cont[] = $this->buildAttach( $att , $boundary , false ) ;
  2435. }if( 'BOTH' === $value ){
  2436. $ret_cont[] = $this->buildAttach( $att , $boundary , $this->isSetCid( $att ) ) ;
  2437. }
  2438. }
  2439. break;
  2440. case 'html':
  2441. $this->content['ORG_CONTENT'] = $this->content['HTML'];
  2442. list( $content , $charset , $enc ) = $this->makeContentText( $this->content['HTML'] , 'HTML' );
  2443. $ret_header['Content-Type'] = 'text/html; charset="' . $charset . '"';
  2444. $ret_header['Content-Transfer-Encoding'] = $enc ;
  2445. $ret_cont = $content ;
  2446. break;
  2447. case 'plain':
  2448. list( $content , $charset , $enc ) = $this->makeContentText( $this->content['TEXT'] , 'TEXT' );
  2449. $ret_header['Content-Type'] = 'text/plain; charset="' . $charset . '"';
  2450. $ret_header['Content-Transfer-Encoding'] = $enc ;
  2451. $ret_cont = $content ;
  2452. break;
  2453. case 'omit':
  2454. $one = null;
  2455. break;
  2456. }
  2457. if( !empty($ret_cont) ){
  2458. $ret[] = array( 'BOUNDARY' => '--' . $boundary , 'HEADER' => $ret_header , 'CONTENT' => $ret_cont );
  2459. }
  2460. }
  2461. }
  2462. return $ret ;
  2463. }
  2464. function renderBody(){
  2465. if( ( 0 === count( $this->body_structure ) ) && !$this->body_empty_allow ){
  2466. return $this->errorGather('Empty Body do not allowed. If you want to send empty Mail , use method -> bodyEmptyAllow(true)' ,__LINE__) ;
  2467. }elseif( 0 === count( $this->body_structure ) ){
  2468. $this->body_structure[0]['HEADER'] = array();
  2469. }
  2470. if( !$this->smime ){
  2471. foreach( $this->body_structure[0]['HEADER'] as $key => $value){
  2472. $this->header_content_type[$key]=$value;
  2473. }
  2474. $this->body_structure[0]['HEADER'] = array();
  2475. }
  2476. $this->body_structure[0]['BOUNDARY'] = null;
  2477. $this->content_for_mailfunction = rtrim($this->finalize( $this->body_structure )) ;
  2478. $this->body_already_build = true ;
  2479. }
  2480. function finalize( $array ){
  2481. foreach( $array as $ar ){
  2482. $header = $this->expandHeader( $ar['HEADER'] );
  2483. $bd = isset($ar['BOUNDARY']) ? trim($ar['BOUNDARY']) . $this->LFC : null ;
  2484. if(is_array($ar['CONTENT'])){
  2485. if( !empty( $header ) ){
  2486. $this->body = $this->body . $bd . $header . $this->LFC . $this->LFC ;
  2487. }
  2488. $this->finalize( $ar['CONTENT'] );
  2489. }else{
  2490. if( !empty( $header ) ){
  2491. $header .= $this->LFC . $this->LFC ;
  2492. }
  2493. $add = $bd . $header . $ar['CONTENT'] ;
  2494. $this->body = $this->body . $add . $this->LFC . $this->LFC ;
  2495. }
  2496. }
  2497. return $this->body;
  2498. }
  2499. function expandHeader( $hds ){
  2500. if(empty($hds)){
  2501. return null;
  2502. }
  2503. $header = null;
  2504. foreach( $hds as $key => $value ){
  2505. if( isset( $value ) ){
  2506. $header .= $key . ': ' . $value . $this->LFC;
  2507. }
  2508. }
  2509. return trim($header);
  2510. }
  2511. function makeBoundary(){
  2512. static $rec = 0 ;
  2513. $boundary = '__Next-' . $rec . '-' . $this->qdmail_md( null , 65 , 90 ) . 'UWRtYWlsIEFHUEx2Mw==' . base64_encode( $this->qdmail_md() ) . '__';
  2514. $rec ++ ;
  2515. return $boundary;
  2516. }
  2517. function makeContentText( $content , $is_text = 'TEXT' ){
  2518. $flag_wrp = ( 'TEXT' == $is_text ) ? true:false;
  2519. $enc = ( 'HTML' == $is_text ) ? $this->content_transfer_enc_html : $this->content_transfer_enc_text ;
  2520. if( is_array( $content ) ){
  2521. $content = array_change_key_case( $content , CASE_UPPER );
  2522. $_content = $content['CONTENT'];
  2523. $org_char = $this->qdmail_system_charset ; //already converted to system charaset
  2524. $target_char = isset($content['_CHARSET'])
  2525. ? $content['_CHARSET'] : $this->charset_content;
  2526. $length = isset($content['LENGTH'])
  2527. ? $content['LENGTH'] : $this->wordwrap_length;
  2528. $content_transfer_enc = !empty($content['ENC'])
  2529. ? $content['ENC'] : $enc;
  2530. $content = $_content;
  2531. }else{
  2532. $org_char = $this->qdmail_system_charset ;
  2533. $target_char = $this->charset_content;
  2534. $length = $this->wordwrap_length;
  2535. $content_transfer_enc = $enc;
  2536. }
  2537. // fix crlf
  2538. list($content,$void) = $this->clean($content);
  2539. // Content_replace
  2540. if( $this->simple_replace ){
  2541. $content = $this->replace( $content , $this->to[0] );
  2542. }
  2543. // Content-id replace
  2544. if(!$this->content_id_fix){
  2545. $content = $this->replaceCid( $content );
  2546. }
  2547. // content modify by external function at HTML
  2548. if( 'HTML' == $is_text && isset($this->deco_kind) && isset($this->deco_def[$this->deco_kind]['HTML_EXTERNAL']) ){
  2549. $temp = $this->deco_def[$this->deco_kind]['HTML_EXTERNAL'];
  2550. if( is_array( $temp ) && 'this'==$temp[0]){
  2551. $content = $this->{$temp[1]}($content);
  2552. }elseif( !empty( $temp ) ){
  2553. $content = call_user_func( array($temp[0],$temp[1]) , $content);
  2554. }
  2555. }
  2556. if( $this->wordwrap_allow && $flag_wrp && false !== $length ){
  2557. $content = $this->mbWordwrap( $content , $length );
  2558. }
  2559. $enc_upp = strtoupper($content_transfer_enc);
  2560. if( $this->kana && 'ja'===$this->language && (('BASE64' === $enc_upp && $this->kana_content_relation) || 'BASE64' !== $enc_upp )){
  2561. $content = mb_convert_kana( $content , 'KV' , $org_char );
  2562. }
  2563. $content = $this->qd_convert_encoding( $content , $target_char , $org_char );
  2564. if( 'BASE64' == $enc_upp && !empty( $content ) ){
  2565. $content = chunk_split( base64_encode( $content ) );
  2566. }elseif( ( 'QUOTED-PRINTABLE' == $enc_upp || 'QP' == $enc_upp ) && !empty( $content ) ){
  2567. $content_transfer_enc = 'quoted-printable';
  2568. $content = $this->quotedPrintableEncode( $content );
  2569. }
  2570. return array( $content , $target_char , $content_transfer_enc );
  2571. }
  2572. //--------------
  2573. // html => text
  2574. // must utf-8 because of preg_replace & strip_tags function
  2575. //--------------
  2576. function htmlToText( $html ){
  2577. $_content = str_replace( array( "\r" , "\n" ) , '' , $html );
  2578. $_content = preg_replace( array( '/<br>/i','/<\/p>/i' , '/<br\s*\/>/i' , '/<\/div>/i' , '/<\/h[1-9]>/i' , '/<\/ol>/i' , '/<\/dl>/i' , '/<\/ul>/i' , '/<li>/i' , '/<\/li>/i' , '/<\/dd>/i' , '/<\/blockquote>/i' , '/<hr\s*\/?>/i' , '/<\/tr>/i' , '/<\/caption>/i' ), $this->LFC , $_content );
  2579. $_content = preg_replace( array( '/<\/td>/i' , '/<\/th>/i' ), ' ' , $_content );
  2580. $_content = preg_replace( "/\\r?\\n/", "\n" , $_content );
  2581. $_content = preg_replace( "/[\\n]+/", "\n" , $_content );
  2582. $_content = preg_replace( "/\\n/", $this->LFC , $_content );
  2583. return trim(strip_tags($_content));
  2584. }
  2585. function mimeEncode( $subject , $charset , $org_charset = null , $first_line_front_words_length = 12 ) {
  2586. $enc = isset($org_charset) ? $org_charset:$this->qd_detect_encoding($subject);
  2587. if( empty($subject) || ( strlen(bin2hex($subject))/2 == mb_strlen($subject,$enc) ) ){
  2588. return trim(chunk_split($subject, $this->mime_encode_max, "\r\n "));
  2589. }
  2590. if($this->kana && 'ja'===$this->language){
  2591. $subject = mb_convert_kana( $subject , 'KV' , $enc );
  2592. }
  2593. $subject = $this->qd_convert_encoding( $subject , $charset , $enc );
  2594. $start = "=?" . $charset . "?B?";
  2595. $end = "?=";
  2596. $spacer = $end . $this->LFC . chr(9) . $start;
  2597. $length = $this->mime_encode_max - strlen($start) - strlen($end);
  2598. $pointer = 1;
  2599. $cut_start = 0;
  2600. $line = null;
  2601. $_ret = array();
  2602. $max = mb_strlen( $subject ,$charset );
  2603. while( $pointer <= $max ){
  2604. $line = mb_substr( $subject , $cut_start , $pointer-$cut_start , $charset );
  2605. $bs64len = strlen(bin2hex(base64_encode($line)))/2;
  2606. if( (0!==count($_ret) && $bs64len <= $length) || (0===count($_ret) && $bs64len <= ($length-$first_line_front_words_length)) ){
  2607. $pointer ++;
  2608. }else{
  2609. $_ret[] = base64_encode($line) ;
  2610. $cut_start = $pointer;
  2611. }
  2612. }
  2613. if( strlen( trim( $line ) ) > 0){
  2614. $_ret[] = base64_encode( $line );
  2615. }
  2616. $ret = $start . implode( $spacer , $_ret ) . $end;
  2617. $ret = preg_replace(array('/\0/is','/\r[^\n]/is'),'',$ret);
  2618. return $ret ;
  2619. }
  2620. function extractAddr($addr_including_sclub){
  2621. if( preg_match( '/<([^>]+)>/' , $addr_including_sclub , $match ) == 0){
  2622. $addr = $addr_including_sclub;
  2623. }else{
  2624. $addr = $match[1];
  2625. }
  2626. $temp = $this->address_validation_method;
  2627. if( is_array( $temp ) && 'this'==$temp[0]){
  2628. $fg = $this->{$temp[1]}( $addr );
  2629. $mess ="System";
  2630. }elseif( !empty( $temp ) ){
  2631. $fg = call_user_func( array($temp[0],$temp[1]) , $addr );
  2632. $mess ="USER";
  2633. }
  2634. if( $fg ){
  2635. return $addr ;
  2636. }else{
  2637. return $this->errorGather('Illegal Mail Address'.$mess.'Validete Address Method' ,__LINE__) ;
  2638. }
  2639. }
  2640. //----------------------------------------------------------------
  2641. // Charset ReDecear - if Decoration Pattern needs anather charset
  2642. // (Overload)
  2643. //----------------------------------------------------------------
  2644. function _charsetDefFix(){
  2645. if( !isset( $this->deco_kind ) ){
  2646. return ;
  2647. }
  2648. if(isset($this->deco_def[$this->deco_kind]['_CHARSET'])){
  2649. $this->charset_content = $this->deco_def[$this->deco_kind]['_CHARSET'];
  2650. }
  2651. if(isset($this->deco_def[$this->deco_kind]['ENC_TEXT'])){
  2652. $this->content_transfer_enc_text = $this->deco_def[$this->deco_kind]['ENC_TEXT'];
  2653. }
  2654. if(isset($this->deco_def[$this->deco_kind]['ENC_HTML'])){
  2655. $this->content_transfer_enc_html = $this->deco_def[$this->deco_kind]['ENC_HTML'];
  2656. }
  2657. }
  2658. //------------------------------------------------------------
  2659. // Addition Header(in send( param ) ) set to $this->{to} etc.
  2660. // and return UpperCase keys
  2661. //------------------------------------------------------------
  2662. function setAddr( $header ){
  2663. if( empty( $header ) ){
  2664. return array( $header , array() );
  2665. }
  2666. list( $header , $link_hd )= $this->keyUpper( $header );
  2667. foreach( $this->addr_many as $section => $void){
  2668. if( !isset( $header[strtoupper($section)] ) ){
  2669. continue;
  2670. }
  2671. $this->{strtolower( $section )}( $header[strtoupper($section)] , null , true );
  2672. unset( $header[strtoupper( $section )] );
  2673. }
  2674. // TO Separate mode?
  2675. if( true === $this->toSeparate() ){
  2676. $this->cc(false);
  2677. $this->bcc(false);
  2678. }
  2679. return array( $header , $link_hd );
  2680. }
  2681. function convertCharsetRecursive( $array , $target_enc ){
  2682. if( is_array( $array ) && !empty( $array['_ORG_CHARSET'] ) ){
  2683. foreach($array as $key => $value){
  2684. if( false === strpos( $key , '_CHARSET' ) ){
  2685. $array[$key] = $this->qd_convert_encoding($value , $target_enc ,$array['_ORG_CHARSET'] );
  2686. }
  2687. }
  2688. }elseif( is_string( $array ) || is_numeric( $array ) ){
  2689. $enc = $this->qd_detect_encoding( $array );
  2690. $array = $this->qd_convert_encoding($array , $target_enc , $enc );
  2691. }elseif( is_array( $array ) ){
  2692. foreach( $array as $key => $value ){
  2693. $ret[$key] = $this->convertCharsetRecursive( $value , $target_enc );
  2694. }
  2695. $array = $ret ;
  2696. }elseif( empty( $array ) ){
  2697. $array = null ;
  2698. }else{
  2699. $this->error[]='Error convertCharsetRecursive, invalid type ,line->'.__LINE__;
  2700. }
  2701. return $array ;
  2702. }
  2703. function extractrecipient(){
  2704. $hd = array('to','cc','bcc') ;
  2705. $ret = array();
  2706. foreach( $hd as $hdn ){
  2707. foreach($this->{$hdn} as $addr ){
  2708. $ret[] = $addr[$this->tokey['_ADDR']] ;
  2709. }
  2710. }
  2711. if( 0 === count( $ret ) ){
  2712. return $this->errorGather('No recipient' ,__LINE__) ;
  2713. }else{
  2714. $this->recipient = $ret ;
  2715. return $this->errorGather();
  2716. }
  2717. }
  2718. //------------------------------------------------------------------------
  2719. // Attachment Routine
  2720. // attach - set to $this->attach array
  2721. // attach OneArray(1 array pattern array('path','attacheName'))
  2722. // attach Singe (2 string pattern ('path','attacheName') )
  2723. // attachFull - Base Routine allattch routine call him
  2724. // buildAttach - called buildBody method
  2725. //------------------------------------------------------------------------
  2726. //
  2727. //
  2728. //array('path_filename','attach_name','mime_type','target_charset','org_charset', );
  2729. //
  2730. //
  2731. //
  2732. function attach( $param , $add = false ){
  2733. list( $stack , $this->attach ) = array( $this->attach , array() );
  2734. if(is_string($param)){
  2735. $param = array($param);
  2736. }
  2737. if( ($this->inline_mode || $this->simple_attach) && !is_array($param[0])){
  2738. foreach($param as $one){
  2739. $param_temp[] = array( $one );
  2740. }
  2741. $param = $param_temp;
  2742. }
  2743. $te_st = reset($param);
  2744. if(!is_array($te_st)){
  2745. $param = array( $param );
  2746. }
  2747. foreach($param as $par){
  2748. if(empty($par)){
  2749. continue;
  2750. }
  2751. $path_filename = isset($par['PATH']) ? $par['PATH']:$par[0];
  2752. if(isset($par['NAME'])){
  2753. $attach_name = $par['NAME'];
  2754. }elseif(isset($par[1])){
  2755. $attach_name = $par[1];
  2756. }else{
  2757. $attach_name = basename( $path_filename ) ;
  2758. }
  2759. $mime_type = null;
  2760. if(isset($par['CONTENT-TYPE'])){
  2761. $mime_type = $par['CONTENT-TYPE'];
  2762. }elseif(isset($par['MIME-TYPE'])){
  2763. $mime_type = $par['MIME-TYPE'];
  2764. }elseif(isset($par[2])){
  2765. $mime_type = $par[2];
  2766. }
  2767. $content_id = null;
  2768. if(isset($par['CONTENT-ID'])){
  2769. $content_id = $par['CONTENT-ID'];
  2770. }elseif(isset($par[3])){
  2771. $content_id = $par[3];
  2772. }
  2773. $target_charset = null;
  2774. if(isset($par['_CHARSET'])){
  2775. $target_charset = $par['_CHARSET'];
  2776. }elseif(isset($par[4])){
  2777. $target_charset = $par[4];
  2778. }
  2779. $org_charset = null;
  2780. if(isset($par['_ORG_CHARSET'])){
  2781. $org_charset = $par['_ORG_CHARSET'];
  2782. }elseif(isset($par[5])){
  2783. $org_charset = $par[5];
  2784. }
  2785. $direct = null;
  2786. if(isset($par['DIRECT'])){
  2787. $direct = $par['DIRECT'];
  2788. }elseif(isset($par[6])){
  2789. $direct = $par[6];
  2790. }
  2791. $bare = false;
  2792. if(isset($par['BARE'])){
  2793. $bare = $par['BARE'];
  2794. }elseif(isset($par[7])){
  2795. $bare = $par[7];
  2796. }
  2797. $this->attach[] = array(
  2798. 'PATH' => $path_filename,
  2799. 'NAME' => $attach_name,
  2800. 'CONTENT-TYPE' => $mime_type,
  2801. 'CONTENT-ID' => $content_id,
  2802. '_CHARSET' => $target_charset,
  2803. '_ORG_CHARSET' => $org_charset,
  2804. 'DATA' => $direct,
  2805. 'DIRECT' => isset($direct) ,
  2806. 'BARE' => $bare,
  2807. );
  2808. }
  2809. if($add){
  2810. $this->attach = array_merge( $stack , $this->attach );
  2811. }
  2812. $this->attach_already_build = false ;
  2813. return $this->errorGather() ;
  2814. }
  2815. //--------------------------------------------------------
  2816. // Build attachment one file , called by buildBody method
  2817. // $one is array , no recursive ,must ['PATH'] element
  2818. //--------------------------------------------------------
  2819. function buildAttach( $one , $boundary , $inline){
  2820. $ret_boundary = null;
  2821. $ret_header = array();
  2822. $ret_content = null;
  2823. $one = array_change_key_case( $one , CASE_UPPER);
  2824. if( !isset($one['NAME'] )){
  2825. $one['NAME'] = basename( $one['PATH'] );
  2826. }
  2827. //Content-Type
  2828. if( isset( $one['CONTENT-TYPE'] )){
  2829. $type = $one['CONTENT-TYPE'];
  2830. }elseif( 0 != preg_match( '/\.([^\.]+)$/' , $one['NAME'] , $matches )){
  2831. $type = isset( $this->attach_ctype[strtolower($matches[1])] )
  2832. ? $this->attach_ctype[strtolower($matches[1])] : 'unkown';
  2833. }elseif(0 != preg_match( '/\.([^\.]+)$/' , $one['PATH'] , $matches )){
  2834. $type = isset( $this->attach_ctype[strtolower($matches[1])])
  2835. ? $this->attach_ctype[strtolower($matches[1])] : 'unkown';
  2836. if( $this->auto_ext && 'unkown' != $type ){
  2837. $one['NAME'] .= '.'.$matches[1];
  2838. }
  2839. }else{
  2840. $type = 'unkown';
  2841. }
  2842. if( isset( $one['_CHARSET'] ) ){
  2843. $charset = $one['_CHARSET'];
  2844. }else{
  2845. $charset = $this->charset_attach_filename;
  2846. }
  2847. if( isset( $one['_ORG_CHARSET'] ) ){
  2848. $org_charset = $one['_ORG_CHARSET'];
  2849. }else{
  2850. $org_charset = null;
  2851. }
  2852. $filename = $this->mimeEncode( $one['NAME'] , $charset , $org_charset , 20 );
  2853. //is Inline ?
  2854. if( $inline ){
  2855. $id = $this->content_id_fix ? $one['CONTENT-ID']:$this->makeContentId($one['CONTENT-ID']);
  2856. $content_id = '<' . $id . '>' ;
  2857. $content_disposition = 'inline';//attachment for au?
  2858. }else{
  2859. $content_id = null ;
  2860. $content_disposition = 'attachment';
  2861. }
  2862. // do it need Disposition Heaer ?
  2863. if( isset( $this->deco_kind ) && false===$this->deco_def[$this->deco_kind]['DISPOSITION']){
  2864. $disposition = null;
  2865. }else{
  2866. $disposition = $content_disposition.';'.$this->LFC
  2867. .' filename="'.$filename.'"'
  2868. ;
  2869. }
  2870. $ret_boundary = '--'.$boundary ;
  2871. $ret_header['Content-Type'] = $type.'; name="'.$filename.'"'
  2872. ;
  2873. $ret_header['Content-Transfer-Encoding'] = 'base64' ;
  2874. $ret_header['Content-Id'] = isset($content_id) ? trim( $content_id ) : null ;
  2875. if(!empty($disposition)){
  2876. $ret_header['Content-Disposition'] = $disposition;
  2877. }
  2878. if( !empty( $one['DIRECT'] ) ){
  2879. $cont=$one['DATA'];
  2880. }else{
  2881. $path_filename = $this->attachPathFix( $one['PATH'] );
  2882. if( !file_exists ( $path_filename )){
  2883. $this->error[]='No attach file \''.$path_filename.'\' line->'.__LINE__;
  2884. return false;
  2885. }else{
  2886. $cont=file_get_contents( $path_filename );
  2887. }
  2888. }
  2889. if( isset( $one['BARE'] ) && true === $one['BARE'] ){
  2890. $ret_content = $one['DATA'];
  2891. }else{
  2892. $ret_content = trim(chunk_split(base64_encode($cont)));
  2893. }
  2894. $this->attach_already_build = true;
  2895. return array(
  2896. 'BOUNDARY' =>$ret_boundary ,
  2897. 'HEADER' =>$ret_header ,
  2898. 'CONTENT' =>$ret_content
  2899. );
  2900. }
  2901. function isSetCid( $array ){
  2902. return isset( $array['CONTENT-ID'] ) && ( '' !== $array['CONTENT-ID'] ) ;
  2903. }
  2904. function makeContentId( $id ){
  2905. if( is_null( $this->after_id ) ){
  2906. $fromaddr = isset($this->header['From'][0]) ? $this->extractAddr($this->header['From'][0]):null;
  2907. $this->after_id = mt_rand() . '_'. str_replace(array('@','-','/','.'),'', $fromaddr .'_'. $this->xmailer.'_'.$this->version );
  2908. }
  2909. return str_replace(array('@','-','/','.'),'', 'id_'.$id ).'_@_'. $this->after_id ;
  2910. }
  2911. function replaceCid( $content ){
  2912. if( !isset( $this->deco_kind ) ){
  2913. return $content;
  2914. }
  2915. foreach($this->attach as $att){
  2916. if( $this->isSetCid( $att ) ){
  2917. $orig = preg_quote($att['CONTENT-ID'] ,'/');
  2918. $rep = $this->makeContentId( $att['CONTENT-ID'] );
  2919. $content = preg_replace('/(<\s*img[^>]+src\s*=\s*"cid:)' . $orig . '("[^>]*>)/is','${1}'.$rep.'${2}' ,$content);
  2920. }
  2921. }
  2922. return $content ;
  2923. }
  2924. function attachDirect( $attach_name , $data , $add = false , $mime_type = null , $content_id = null , $target_charset = null , $charset_org = null){
  2925. $_att=array();
  2926. $_att[0]['DIRECT'] = true;
  2927. $_att[0]['DATA'] = $data;
  2928. $_att[0]['PATH'] = null;
  2929. $_att[0]['NAME'] = $attach_name ;
  2930. $_att[0]['MIME_TYPE'] = $mime_type ;
  2931. $_att[0]['CONTENT-ID'] = $content_id ;
  2932. $_att[0]['_CHARSET'] = $target_charset;
  2933. $_att[0]['_ORG_CHARSET'] = $charset_org;
  2934. if( $add ){
  2935. $this->attach = array_merge( $this->attach , $_att );
  2936. }else{
  2937. $this->attach = $_att ;
  2938. }
  2939. return $this->errorGather() ;
  2940. }
  2941. function attachPathFix( $path_filename ){
  2942. $temp = substr($path_filename,0,1);
  2943. if( '/' != $temp && '\\' != $temp ){
  2944. return $this->attach_path . $path_filename;
  2945. }
  2946. return $path_filename;
  2947. }
  2948. //---------------------------------------
  2949. //
  2950. // Inteligent Multibyte Wordwrap
  2951. //
  2952. //---------------------------------------
  2953. function mbWordwrap( $word , $length ){
  2954. if( !is_numeric( $length ) ){
  2955. $length = $this->wordwrap_length;
  2956. }
  2957. if( 1 > $length ){
  2958. $this->error[]='Wordwrap length illegal , need more than 1 line->'.__LINE__;
  2959. }
  2960. $ret = array();
  2961. list( $word , $LFC ) = $this->clean( $word );
  2962. $lines = explode( $LFC , $word ) ;
  2963. foreach($lines as $line){
  2964. $ret []= $this->mbWordwrapLine( $line , $length );
  2965. }
  2966. return implode( $this->LFC , $ret );
  2967. }
  2968. function mbWordwrapLine( $line , $length ){
  2969. $skip = false;
  2970. if( 0 != count( $this->wrap_except ) ){
  2971. foreach($this->wrap_except as $word => $begin_flag ){
  2972. $fg = strpos( $line , $word );
  2973. if( ( ( 0 === $fg ) && $begin_flag) || ( ( false !== $fg ) && !$begin_flag) ){
  2974. $skip = true;
  2975. }
  2976. }
  2977. }
  2978. $enc = $this->qd_detect_encoding( $line );
  2979. $len = mb_strlen( $line , $enc );
  2980. if ( ( $len <= $length ) || $skip ) {
  2981. return $line;
  2982. }
  2983. if( $this->wrap_width ){
  2984. $method = 'widthSubStr';
  2985. }else{
  2986. $method = 'defMbSubStr';
  2987. }
  2988. $ret = array();
  2989. $ln = $length;
  2990. $j = 0;
  2991. for( $i=0; $i < $len ; $i += $ln ){
  2992. list( $r , $ln ) = $this->{$method}( $line , $i , $length , $enc );
  2993. if( 0 !== $j ){
  2994. list( $r , $no_top , $flag )=$this->mbProhibitTop( $r , $enc );
  2995. if( $flag ){
  2996. $ret[$j-1] .= $no_top ;
  2997. $i += mb_strlen( $no_top , $enc );
  2998. list( $r , $ln ) = $this->{$method}( $line , $i , $length , $enc );
  2999. }
  3000. }
  3001. if( ( $i + $ln ) < $len ){
  3002. list( $_r , $ret_count , $flag )=$this->mbProhibitEnd( $r , $enc );
  3003. if( $flag && ( $ret_count < ($length-1) ) ){
  3004. $i -= $ret_count;
  3005. $r = $_r;
  3006. }
  3007. }
  3008. $ret [$j++]= $r ;
  3009. }
  3010. return implode( $this->LFC , $ret ) ;
  3011. }
  3012. function defMbSubStr( $line , $start , $length , $enc ){
  3013. return array( mb_substr( $line , $start , $length , $enc ) ,$length );
  3014. }
  3015. function widthSubStr( $line , $start , $length , $enc ){
  3016. $ret = array();
  3017. $max = mb_strlen( $line , $enc ) ;
  3018. $target = mb_substr( $line , $start , $length , $enc ) ;
  3019. $point = $start + $length;
  3020. // mb_strwidth's lengh means ascii width
  3021. while( ( mb_strwidth( $target , $enc ) <= ( $length-1 ) * $this->mb_strwidth_magni ) && ( $point < $max ) ){
  3022. $target .= mb_substr( $line , $point++ , 1 , $enc ) ;
  3023. }
  3024. return array( $target , mb_strlen( $target , $enc ) ) ;
  3025. }
  3026. function mbProhibitTop( $line , $enc ){
  3027. $flag = false;
  3028. $ret = null;
  3029. $len = mb_strlen( $line , $enc );
  3030. $count = 0 ;
  3031. do{
  3032. $top = mb_substr( $line , $count++ , 1 , $enc );
  3033. }while( isset($this->wrap_prohibit[$top]) && $this->wrap_prohibit[$top] && ( abs($count) < $len ) );
  3034. -- $count ;
  3035. if( 0 < $count ){
  3036. $ret = mb_substr( $line , 0 , $count , $enc );
  3037. $line = mb_substr( $line , $count , $len - $count , $enc );
  3038. $flag = true;
  3039. }
  3040. return array( $line , $ret , $flag );
  3041. }
  3042. function mbProhibitEnd( $line , $enc ){
  3043. $flag = false;
  3044. $len = mb_strlen( $line , $enc );
  3045. $count = 0 ;
  3046. do{
  3047. $end = mb_substr( $line , --$count , 1 , $enc );
  3048. }while( isset($this->wrap_prohibit[$end]) && !$this->wrap_prohibit[$end] && ( abs($count) < $len ) );
  3049. $count = abs( ++$count );
  3050. if( 0 < $count ){
  3051. $line = mb_substr( $line , 0 , $len - $count , $enc );
  3052. $flag = true;
  3053. }
  3054. return array( $line , $count , $flag );
  3055. }
  3056. //------------------------
  3057. // utility
  3058. //------------------------
  3059. function issetContent( $array ){
  3060. if( !isset( $array ) ){
  3061. return false ;
  3062. }
  3063. if( isset( $array['CONTENT'] ) ){
  3064. return true ;
  3065. }
  3066. if( isset( $array ) && is_string( $array ) ){
  3067. return true ;
  3068. }
  3069. return false ;
  3070. }
  3071. function keyUpper( $array ){
  3072. $up_array = array_change_key_case( $array , CASE_UPPER );
  3073. $link = $this->qdmail_array_combine( array_keys( $up_array ) , array_keys( $array ));
  3074. return array( $up_array , $link );
  3075. }
  3076. function qdmail_array_combine( $keys , $values ){//for php4
  3077. if( !is_array( $keys ) || !is_array( $values ) ){
  3078. $this->error[]='array_conbine needs array line =>'.__LINE__;
  3079. }
  3080. $ret = array();
  3081. reset( $values );
  3082. foreach( $keys as $key ){
  3083. $ret[$key] = array_shift( $values ) ;
  3084. }
  3085. return $ret;
  3086. }
  3087. function qdmail_md( $col = null , $start = 33 , $end = 126 ){
  3088. if( is_null( $col ) ){
  3089. $col = $this->boundary_base_degit ;
  3090. }
  3091. $ret = null;
  3092. for( $i = 0 ; $i < $col ; $i++){
  3093. $ret .= chr( mt_rand( $start , $end ) ) ;
  3094. }
  3095. return $ret;
  3096. }
  3097. function clean( $content ){
  3098. if($this->smtp ){
  3099. $LFC = $this->LFC;
  3100. }else{
  3101. $LFC = chr(10);
  3102. }
  3103. return array(rtrim( preg_replace( '/\r?\n/' , $LFC , $content ) ),$LFC);
  3104. }
  3105. function quotedPrintableEncode( $word ){
  3106. if(empty($word)){
  3107. return $word;
  3108. }
  3109. $lines = preg_split("/\r?\n/", $word);
  3110. $out = array() ;
  3111. foreach ($lines as $line){
  3112. $one_line = null ;
  3113. for ($i = 0; $i <= strlen($line) - 1; $i++){
  3114. $char = substr ( $line, $i, 1 );
  3115. $ascii = ord ( $char );
  3116. if ( (32 > $ascii) || (61 == $ascii) || (126 < $ascii) ){
  3117. $char = '=' . strtoupper ( dechex( $ascii ) );
  3118. }
  3119. if ( ( strlen ( $one_line ) + strlen ( $char ) ) >= 76 ){
  3120. $out[]= $one_line . '=' ;
  3121. $one_line = null ;
  3122. }
  3123. $one_line .= $char;
  3124. }
  3125. $out[]= $one_line ;
  3126. }
  3127. return implode( $this->LFC , $out );
  3128. }
  3129. function time(){
  3130. list($start_usec, $start_sec) = explode(' ', $this->start_time );
  3131. list($end_usec, $end_sec) = explode(' ', microtime() );
  3132. return ($end_sec - $start_sec) + (float) ($end_usec - $start_usec);
  3133. }
  3134. //------------------
  3135. // error
  3136. //------------------
  3137. function errorStatment( $type = false , $lf = null ){
  3138. if( $type ){
  3139. return $this->errorRender( $this->error_stack , $lf , false );
  3140. }else{
  3141. return $this->error_stack;
  3142. }
  3143. }
  3144. function errorRender( $error = null , $lf = null , $display = true ){
  3145. if( is_null( $error ) ){
  3146. $error = $this->error;
  3147. }
  3148. if( is_null( $lf ) ){
  3149. $lf = $this->log_LFC ;
  3150. }
  3151. if( !is_array( $error ) ){
  3152. $error = array( $error );
  3153. }
  3154. $out = null ;
  3155. foreach($error as $mes){
  3156. $out .= $this->name . ' error: ' . trim( $mes ) . $lf ;
  3157. }
  3158. if( $this->error_display && $display ){
  3159. $_out = str_replace( $lf ,'<br>' . $lf , $out );
  3160. echo $_out ;
  3161. }
  3162. return $out ;
  3163. }
  3164. function errorGather( $message = null , $line = null){
  3165. if( !is_null( $message ) ){
  3166. if( !is_null( $line ) ){
  3167. $message .= ' line -> '.$line;
  3168. }
  3169. if(0 === count( $this->error_stack )){
  3170. $this->error[] = 'Qdmail Version '.$this->version.' ,PHP Version '.phpversion();
  3171. $this->error[] = $this->iniGather();
  3172. }
  3173. $this->error[] = $message ;
  3174. }elseif( 0 === count( $this->error )){
  3175. return true;
  3176. }
  3177. $er = $this->errorRender();
  3178. $this->error_stack = array_merge( $this->error_stack , $this->error );
  3179. $this->error = array();
  3180. if( !$this->logWrite( 'error' , $er ) ){
  3181. $this->error_stack = array_merge( $this->error_stack , $this->error );
  3182. }
  3183. return false;
  3184. }
  3185. function log( $mes = null ){
  3186. if( is_null( $mes )){
  3187. $addrs = $this->done() ;
  3188. // $this->done = array();
  3189. $spacer = null;
  3190. if( 0 != count( $addrs ) ){
  3191. $mes .= 'Send Success: '.implode(' ',$addrs) ;
  3192. $spacer = $this->log_LFC ;
  3193. }
  3194. $addrs = $this->undone() ;
  3195. // $this->undone = array();
  3196. if( 0 != count( $addrs ) ){
  3197. $mes .= $spacer . 'Send failure: '.implode(' ',$addrs);
  3198. }
  3199. }
  3200. return $this->logWrite( null , trim( $mes ) ) ;
  3201. }
  3202. function logWrite( $type , $message ){
  3203. $tp = ('error' == $type) ? false:true;
  3204. $level = $tp ? $this->log_level:$this->errorlog_level;
  3205. $fg_debug = ( 2 > $this->debug ) && !$this->render_mode;
  3206. if( 0 == $level || !$fg_debug){
  3207. return true;
  3208. }
  3209. $filename = $tp ? $this->log_filename:$this->errorlog_filename;
  3210. $path = $tp ? $this->log_path:$this->errorlog_path;
  3211. $ap = $tp ? $this->log_append:$this->errorlog_append;
  3212. $fp = fopen( $path.$filename , $ap );
  3213. if( !is_resource( $fp ) ){
  3214. $this->error[]='file open error at logWrite() line->'.__LINE__;
  3215. return false;
  3216. }
  3217. $spacer = $tp ? ' ' : $this->log_LFC ;
  3218. fwrite( $fp ,
  3219. date( $this->log_dateformat )
  3220. . $spacer
  3221. . trim( $message )
  3222. . $this->log_LFC
  3223. );
  3224. if( $level > 1 ){
  3225. fwrite( $fp , trim( $this->header_for_smtp ) . $this->log_LFC );
  3226. }elseif( $level > 2 ){
  3227. fwrite( $fp , $this->log_LFC . $this->content_for_mailfunction . $this->log_LFC );
  3228. }
  3229. fclose( $fp ) ;
  3230. return true ;
  3231. }
  3232. function errorSpecify( $func , $line , $add_message = null){
  3233. return $this->errorGather($add_message.'User Specify Error in Method of \''.$func.'\'' , $line ) ;
  3234. }
  3235. //-------------------------------------------
  3236. // MIME Content-type def
  3237. //-------------------------------------------
  3238. var $attach_ctype=array(
  3239. 'txt'=>'text/plain',
  3240. 'csv'=>'text/csv',
  3241. 'xml'=>'text/xml',
  3242. 'htm'=>'text/html',
  3243. 'html'=>'text/html',
  3244. 'gif'=>'image/gif',
  3245. 'jpg'=>'image/jpeg',
  3246. 'jpeg'=>'image/jpeg',
  3247. 'png'=>'image/png',
  3248. 'tif'=>'image/tiff',
  3249. 'tiff'=>'image/tiff',
  3250. 'bmp'=>'image/x-bmp',
  3251. 'ps'=>'appilcation/postscript',
  3252. 'eps'=>'appilcation/postscript',
  3253. 'epsf'=>'appilcation/postscript',
  3254. 'ai'=>'application/postscript',
  3255. 'zip'=>'application/zip',
  3256. 'lzh'=>'application/x-lzh',
  3257. 'lha'=>'application/octet-stream',
  3258. 'tar'=>'application/x-tar',
  3259. 'gzip'=>'application/x-tar',
  3260. 'cpt'=>'application/mac-compactpro',
  3261. 'doc'=>'application/msword',
  3262. 'xls'=>'application/vnd.ms-excel',
  3263. 'ppt'=>'application/vnd.ms-powerpoint',
  3264. 'rtf'=>'application/rtf',
  3265. 'pdf'=>'application/pdf',
  3266. 'css'=>'application/css',
  3267. 'au'=>'audio/basic',
  3268. 'rpm'=>'audio/x-pn-realaudio-plugin',
  3269. 'swa'=>'application/x-director',
  3270. 'mp3'=>'audio/mpeg',
  3271. 'mp4'=>'audio/mp4',
  3272. 'wav'=>'audio/x-wav',
  3273. 'midi'=>'audio/midi',
  3274. 'avi'=>'vide/x-msvideo',
  3275. 'mpeg'=>'video/mpeg',
  3276. 'mpg'=>'video/mpeg',
  3277. 'wmv'=>'video/x-ms-wmv',
  3278. 'flash'=>'application/x-shockwave-flash',
  3279. 'mmf'=>'application/x-smaf ', //softbank chakumero
  3280. 'smaf'=>'application/x-smaf', //softbank chakumero
  3281. 'hdml'=>'text/x-hdml', // HDML au,docomo
  3282. '3gpp2'=>'video/3gpp2', // au chaku-uta,ez-movie
  3283. '3g2'=>'video/3gpp2', // au chaku-uta,ez-movie
  3284. 'amc'=>'video/3gpp2', // au chaku-uta,ez-movie
  3285. 'kjx'=>'application/x-kjx', // au ez-apri
  3286. '3gpp'=>'video/3gpp', // docomo chaku-uta,movie
  3287. '3gp'=>'video/3gpp', // docomo chaku-uta,movie
  3288. 'amr'=>'video/3gpp', // docomo chaku-uta,movie
  3289. 'asf'=>'video/3gpp', // docomo chaku-uta,movie
  3290. 'jam'=>'application/x-jam', // docomo i-apri
  3291. 'jar'=>'application/java-archive', // java apri
  3292. 'jad'=>'text/vnd.sun.j2me.app-descriptor', // java apri
  3293. 'exe'=>'application/octet-stream',
  3294. 'khm'=>'application/x-kddi-htmlmail',// au decoration mail template
  3295. 'dmt'=>'application/x-decomail-template',// nttdocomo decoration mail template
  3296. 'hmt'=>'application/x-htmlmail-template',// softbank decoration mail template
  3297. 'hqx'=>'application/mac-binhex40',
  3298. 'cpt'=>'application/mac-compactpro',
  3299. 'php'=>'application/x-httpd-php',
  3300. 'php4'=>'application/x-httpd-php',
  3301. 'php3'=>'application/x-httpd-php',
  3302. 'phtml'=>'application/x-httpd-php',
  3303. 'phps'=>'application/x-httpd-php-source',
  3304. 'js'=>'application/x-javascript',
  3305. 'swf'=>'application/x-shockwave-flash',
  3306. 'eml'=>'message/rfc822',
  3307. );
  3308. //-------------------------------
  3309. // Debug
  3310. //-------------------------------
  3311. function iniGather(){
  3312. $ret = 'OS '.PHP_OS.' ; PHP Version '.PHP_VERSION.' ; '.$this->name.' version '.$this->version;
  3313. $ret .= $this->LFC.'php.ini status: mb_language = '.mb_language()
  3314. .' ; mb_internal_encoding = '.mb_internal_encoding()
  3315. .' ; mb_detect_order = '.implode(',',mb_detect_order());
  3316. $ret .= $this->LFC . $this->name .' Status debug: '.$this->debug().', log: '.$this->logLevel().', errorlog: '.$this->errorlogLevel();
  3317. return $ret;
  3318. }
  3319. function debug( $level=null ){
  3320. if( is_null( $level ) || !is_numeric($level) ){
  3321. return $this->debug;
  3322. }
  3323. $this->debug = $level ;
  3324. return true;
  3325. }
  3326. function debugEchoLine(){
  3327. $vars = func_get_args();
  3328. $this->debugEcho( false , $vars );
  3329. }
  3330. function debugEchoLf(){
  3331. $vars = func_get_args();
  3332. $this->debugEcho( true , $vars );
  3333. }
  3334. function debugEcho( $lf , $vars = null ){
  3335. static $already_header = false;
  3336. static $already_footer = false;
  3337. if( 1 > $this->debug ){
  3338. return;
  3339. }
  3340. if( true === $this->debug_echo_charset ){
  3341. $this->debug_echo_charset = $this->charset_content ;
  3342. }
  3343. if( !$already_header ){
  3344. $head='<html><head><meta http-equiv="content-type" content="text/html; charset='.$this->debug_echo_charset.'"></head><body>';
  3345. echo $head ;
  3346. echo '<pre>'.$this->name . ' Debug: '.$this->iniGather().'</pre>';
  3347. $already_header = true ;
  3348. }
  3349. if( $already_header && ( 'END' === $lf ) && !$already_footer){
  3350. $foot ='</body></html>';
  3351. echo $foot;
  3352. $already_footer = true;
  3353. return ;
  3354. }
  3355. $out = null;
  3356. if( !is_array( $vars ) ){
  3357. $vars =array( $vars );
  3358. }
  3359. foreach($vars as $var){
  3360. $_out = print_r( $var , true ) ;
  3361. $enc = $this->qd_detect_encoding( $_out );
  3362. if( ( strtoupper( $this->qdmail_system_charset ) !== strtoupper( $enc ) ) && ('ASCII'!==strtoupper( $enc ))){
  3363. $_out = $this->qd_convert_encoding( $_out , $this->qdmail_system_charset , $enc );
  3364. }
  3365. $out .= $_out . $this->LFC;
  3366. }
  3367. $spacer = $this->log_LFC ;
  3368. if( !$lf ){
  3369. $out = preg_replace("/\\r?\\n/",' ',$out);
  3370. $spacer = null ;
  3371. }
  3372. echo "<pre>";
  3373. $out = $this->name . ' Debug: ' . $spacer . trim( $out );
  3374. $out = htmlspecialchars( $out , ENT_QUOTES , $this->qdmail_system_charset);
  3375. $out = $this->qd_convert_encoding($out,$this->debug_echo_charset,$this->qdmail_system_charset);
  3376. echo $out;
  3377. echo "</pre>";
  3378. }
  3379. function debugReport( $var = null ){
  3380. if( is_null( $var ) ){
  3381. return $this->debug_report;
  3382. }
  3383. if( is_bool( $var ) ){
  3384. $this->debug_report = $var;
  3385. return true;
  3386. }
  3387. if( 'FILE' !== $var ){
  3388. return $this->errorSpecify(__FUNCTION__,__LINE__);
  3389. }
  3390. $fg= true;
  3391. $cont = print_r( $this , true );
  3392. $cont .= print_r( $_SERVER , true);
  3393. $date = date("Y_m_d_H_i_s");
  3394. $out = <<<EOF
  3395. Debug Report
  3396. date: {$date}
  3397. name: {$this->name}
  3398. version: {$this->version}
  3399. {$cont}
  3400. EOF;
  3401. $filename = $this->debug_report_path . $this->name.'_debug_report_'.date("Y_m_d_H_i_s") . '.txt';
  3402. if($fp = fopen( $filename , 'w' )){
  3403. fwrite( $fp , $out );
  3404. fclose( $fp );
  3405. }else{
  3406. $this->error[] = 'Can not open file \'' . $filename . '\' line-> ' . __LINE__ ;
  3407. $fg = false;
  3408. }
  3409. return $fg;
  3410. }
  3411. //--
  3412. // this path like this, /home/foo/bar/ or c\:htdocs\foo\bar\ or ./foo/bar/
  3413. // do not forget the last '/' or '\'
  3414. //--
  3415. function debugReportPath( $path = null ){
  3416. if( is_null( $path ) ){
  3417. return $path;
  3418. }
  3419. if( empty( $path ) ){
  3420. $this->debug_report_path = './';
  3421. return true;
  3422. }
  3423. if( is_string( $path ) ){
  3424. $this->debug_report_path = $path;
  3425. return true ;
  3426. }
  3427. return $this->errorSpecify(__FUNCTION__,__LINE__);
  3428. }
  3429. function sendBySmtp( $obj = null ){
  3430. if( !is_null( $obj ) ){
  3431. $this->smtp_object = $obj;
  3432. }
  3433. if( !isset( $this->smtp_object ) || !is_object( $this->smtp_object ) ){
  3434. if( false === ( $this->smtp_object = $this->smtpObject() ) ){
  3435. return $this->errorGather('SMTP Object make \'new\' error',__LINE__);
  3436. }
  3437. }
  3438. $this->smtp_server = array_change_key_case( $this->smtp_server , CASE_UPPER );
  3439. if( !isset( $this->smtp_server['HOST'] ) ){
  3440. $this->smtp_server = array_merge( $this->smtp_server , $this->smtp_object->server() );
  3441. }
  3442. if( !isset( $this->smtp_server['HOST'] ) ){
  3443. return $this->errorGather('No exist SMTP\'s Settings',__LINE__);
  3444. }
  3445. $this->smtp_server['CONTINUE'] = true;
  3446. if( !$this->smtp_object -> server( $this->smtp_server )){
  3447. return $this->errorGather('SMTP Object initialize error',__LINE__);
  3448. }
  3449. if( $this->smtp_loglevel_link ){
  3450. $this->smtp_object -> logLevel( $this->log_level );
  3451. $this->smtp_object -> errorlogLevel( $this->errorlog_level );
  3452. }
  3453. $this->smtp_object -> to( $this->recipient );
  3454. $this->smtp_object -> data( $this->content_all_for_smtp );
  3455. return $this -> smtp_object -> send();
  3456. }
  3457. function sendBySendmail(){
  3458. $temp_name = tempnam ( $this->temporary_path , 'qdmail' );
  3459. if(false===$temp_name){
  3460. return $this->errorGather('Can not make Temporary File ',__LINE__);
  3461. }
  3462. $fp = fopen($temp_name,'w');
  3463. if(false===$temp_name){
  3464. return $this->errorGather('Can not open Temporary File ',__LINE__);
  3465. }
  3466. fputs($fp,$this->content_all_for_smtp);
  3467. fclose($fp);
  3468. $recipient = implode(' ',$this->recipient);
  3469. $sendfg = exec($this->sendmail_path . ' '.$this->mtaOption().' '.$recipient.' < '.$temp_name,$ret);
  3470. $fg = unlink($temp_name);
  3471. if(false===$fg){
  3472. return $this->errorGather('Can not dellete Temporary File ',__LINE__);
  3473. }
  3474. return (false!==$sendfg && empty($sendfg)) || true === $sendfg;
  3475. }
  3476. //------------------------------------------
  3477. // expecting Override on the other FrameWork
  3478. //------------------------------------------
  3479. function & smtpObject( $null = false ){
  3480. if(is_null($null)){
  3481. $this->smtp_object = null;
  3482. return true;
  3483. }
  3484. if( isset( $this->smtp_object ) && is_object( $this->smtp_object ) ){
  3485. return $this->smtp_object;
  3486. }
  3487. if( !class_exists ( 'Qdsmtp' ) && file_exists( 'qdsmtp.php' ) ){
  3488. require_once( 'qdsmtp.php' );
  3489. }elseif( !class_exists ( 'Qdsmtp' ) && !file_exists( 'qdsmtp.php' )){
  3490. return $this->errorGather('Plese load SMTP Program - Qdsmtp http://hal456.net/qdsmtp',__LINE__);
  3491. }
  3492. $this->smtp_object = & new Qdsmtp();
  3493. return $this->smtp_object;
  3494. }
  3495. function setSmtpObject( & $obj ){
  3496. if(is_object($obj)){
  3497. $this->smtp_object = & $obj;
  3498. return true;
  3499. }else{
  3500. return false;
  3501. }
  3502. }
  3503. }//the QdmailBase
  3504. class QdmailUserFunc extends QdmailBase{
  3505. function __construct( $param = null ){
  3506. parent::__construct( $param );
  3507. }
  3508. function validateAddr( $addr ){
  3509. if(0==preg_match( $this->varidate_address_regex , $addr , $match )){
  3510. $this->errorGather('Tyr Varidate Error by regex preg_match(\''.$this->varidate_address_regex . '\') the address is ->'.$addr,__LINE__);
  3511. }else{
  3512. return true;
  3513. }
  3514. }
  3515. function stripCrlf( $word ){
  3516. if( $this->force_change_charset ){
  3517. $enc = $this->qd_detect_encoding( $word ) ;
  3518. $word = $this->qd_convert_encoding( $word , $this->qdmail_system_charset , $enc );
  3519. }
  3520. $word = preg_replace( '/\r?\n/i' , '' , $word );
  3521. if( $this->force_change_charset ){
  3522. $word = $this->qd_convert_encoding( $word , $enc , $this->qdmail_system_charset );
  3523. }
  3524. return $word ;
  3525. }
  3526. }
  3527. class Qdmail extends QdmailUserFunc{
  3528. var $name ='Qdmail';
  3529. function Qdmail( $param = null ){
  3530. if( !is_null($param)){
  3531. $param = func_get_args();
  3532. }
  3533. parent::__construct( $param );
  3534. }
  3535. }
  3536. //-------------------------------------------
  3537. // CakePHP Component
  3538. //-------------------------------------------
  3539. class QdmailComponent extends QdmailUserFunc{
  3540. var $framework = 'CakePHP';
  3541. var $view_dir = 'email';
  3542. var $layout_dir = 'email';
  3543. var $layout = 'default';
  3544. var $template = 'default';
  3545. var $view = null;
  3546. function QdmailComponent( $param = null ){
  3547. if( !is_null($param)){
  3548. $param = func_get_args();
  3549. }
  3550. parent::__construct( $param );
  3551. }
  3552. function startup(&$controller) {
  3553. $this->Controller =& $controller;
  3554. if( defined( 'COMPONENTS' ) ){
  3555. $this->logPath(COMPONENTS);
  3556. $this->errorlogPath(COMPONENTS);
  3557. }
  3558. return;
  3559. }
  3560. //----------------------------
  3561. // Override Parent Method
  3562. //----------------------------
  3563. function & smtpObject(){
  3564. if( isset( $this->Qdsmtp ) && is_object( $this->Qdsmtp ) ){
  3565. return $this->Qdsmtp;
  3566. }
  3567. if( !class_exists ( 'QdsmtpComponent' ) ){
  3568. if( !$this->import( 'Component' , 'Qdsmtp' ) ){
  3569. return $this->errorGather('Qdmail<->CakePHP Component Load Error , the name is Qdsmtp',__LINE__);
  3570. }
  3571. }
  3572. $this->Qdsmtp = & new QdsmtpComponent();
  3573. if( !is_object( $this->Qdsmtp ) ){
  3574. return $this->errorGather('Qdmail<->CakePHP Component making Instance Error , the name is QdsmtpComponent',__LINE__);
  3575. }
  3576. $this->Qdsmtp -> startup( $this->Controller );
  3577. return $this->Qdsmtp;
  3578. }
  3579. //----------------------------
  3580. // Cake Interface
  3581. //----------------------------
  3582. function import( $kind , $name ){
  3583. if( 1.2 > (float) substr(Configure::version(),0,3) ){
  3584. $function_name = 'load' . $kind ;
  3585. if( function_exists( $function_name ) ){
  3586. return $function_name( $name ) ;
  3587. }else{
  3588. return $this->errorGather('Qdmail<->CakePHP ' .$kind .' Load Error , the name is \'' . $name . '\'',__LINE__);
  3589. }
  3590. }else{
  3591. return App::import( $kind , $name ) ;
  3592. }
  3593. }
  3594. function cakeText( $content , $template = null , $layout = null , $org_charset = null , $target_charset = null , $enc = null , $wordwrap_length = null ){
  3595. $this->template = is_null( $template ) ? $this->template : $template ;
  3596. $this->layout = is_null( $layout ) ? $this->layout : $layout ;
  3597. list( $cont , $target_charset , $org_charset ) = $this->cakeRender( $content , 'TEXT' , $org_charset = null , $target_charset );
  3598. return $this->text( $cont , $wordwrap_length , $target_charset , $enc , $org_charset );
  3599. }
  3600. function cakeHtml( $content , $template = null , $layout = null , $org_charset = null , $target_charset = null , $enc = null ){
  3601. $this->template = is_null( $template ) ? $this->template : $template ;
  3602. $this->layout = is_null( $layout ) ? $this->layout : $layout ;
  3603. list( $cont , $target_charset , $org_charset ) = $this->cakeRender( $content , 'HTML' , $org_charset = null , $target_charset );
  3604. return $this->html( $cont , null , $target_charset , $enc , $org_charset );
  3605. }
  3606. function cakeRender( $content , $type , $org_charset = null , $target_charset = null){
  3607. if( is_null( $target_charset ) ){
  3608. $target_charset = $this->charset_content;
  3609. }
  3610. if( !class_exists ( $this->Controller->view ) ){
  3611. if( !$this->import( 'View' , $this->view ) ){
  3612. return $this->errorGather('Qdmail<->CakePHP View Load Error , the name is \''.$this->view.'\'',__LINE__);
  3613. }
  3614. }
  3615. $type = strtolower( $type );
  3616. $view = & new $this->Controller->view( $this->Controller , false );
  3617. $view->layout = $this->layout;
  3618. $mess = null;
  3619. $content = $view->renderElement( $this->view_dir . DS . $type . DS . $this->template , array('content' => $content ) , true );
  3620. if( 1.2 > (float) substr(Configure::version(),0,3) ){
  3621. $view->subDir = $this->layout_dir . DS . $type . DS ;
  3622. }else{
  3623. $view->layoutPath = $this->layout_dir . DS . $type;
  3624. }
  3625. $mess .= $view->renderLayout( $content ) ;
  3626. if( is_null( $org_charset ) ){
  3627. $org_charset = $this->qd_detect_encoding( $mess );
  3628. }
  3629. $mess = $this->qd_convert_encoding( $mess , $target_charset , $org_charset );
  3630. return array( $mess , $target_charset , $org_charset );
  3631. }
  3632. function CakePHP( $param ){
  3633. $param = array_change_key_case( $param , CASE_LOWER );
  3634. extract($param);
  3635. if( isset($type) || 'HTML' == $type ){
  3636. $type ='cakeHtml';
  3637. }else{
  3638. $type = 'cakeText';
  3639. }
  3640. return $this->{$type}( isset($content) ? $content:null, isset($template) ? $template:null , isset($layout) ? $layout:null , isset($org_charset) ? $org_charset: null , isset($target_charset) ? $target_charset:null , isset($enc) ? $enc:null , isset($wordwrap_length) ? $wordwrap_length:null );
  3641. }
  3642. }
  3643. //-------------------------------------------
  3644. // Symfony Addon
  3645. //-------------------------------------------
  3646. class sfQdmail extends QdmailUserFunc{
  3647. var $framework = 'Symfony';
  3648. function __construct( $param = null ){
  3649. if( !is_null($param)){
  3650. $param = func_get_args();
  3651. }
  3652. parent::__construct( $param );
  3653. }
  3654. function setBody( $body ){
  3655. if('HTML'===$this->is_html){
  3656. $this->html( $body );
  3657. }else{
  3658. $this->text( $body );
  3659. }
  3660. }
  3661. function getAltBody(){
  3662. if('HTML'===$this->is_html){
  3663. $content=$this->body();
  3664. return !empty($content['TEXT']['CONTENT']);
  3665. }else{
  3666. return false;
  3667. }
  3668. }
  3669. function setAltBody( $body ){
  3670. $this->text( $body );
  3671. }
  3672. function addStringAttachment($data, $attach_name , $mime_type){
  3673. $this->attachDirect( $attach_name , $data , $add = true , $mime_type );
  3674. }
  3675. function getRawHeader(){
  3676. return $this->header_for_smtp;
  3677. }
  3678. function getRawBody(){
  3679. return $this->$this->content_for_mailfunction;
  3680. }
  3681. function initialize(){
  3682. $this->reset();
  3683. }
  3684. function setCharset($charset){
  3685. $this->charset($charset);
  3686. }
  3687. function getCharset(){
  3688. $ret = $this->charset();
  3689. return $ret['TEXT'];
  3690. }
  3691. function setContentType($content_type){
  3692. if(false===strpos(strtoupper($content_type),'HTML')){
  3693. $this->is_html = 'TEXT';
  3694. }else{
  3695. $this->is_html = 'HTML';
  3696. }
  3697. }
  3698. function getContentType(){
  3699. if('HTML'===$this->is_html){
  3700. return 'text/html';
  3701. }else{
  3702. return 'text/plain';
  3703. }
  3704. }
  3705. function setPriority($priority){
  3706. $pri = array(1=>'high',3=>'normal',5=>'low');
  3707. if(isset($pri[$priority])){
  3708. $this->priority($pri[$priority]);
  3709. return true;
  3710. }else{
  3711. return false;
  3712. }
  3713. }
  3714. function getPriority(){
  3715. $pri = array('HIGH'=>1,'NORMAL'=>3,'LOW'=>5);
  3716. $now_priority = strtoupper($this->priority());
  3717. if(empty($now_priority)){
  3718. return null;
  3719. }
  3720. return $pri[$now_priority];
  3721. }
  3722. function setEncoding($encoding){
  3723. $this->encoding($encoding);
  3724. }
  3725. function getEncoding(){
  3726. return $this->encoding();
  3727. }
  3728. function setSubject($subject){
  3729. $this->subject($subject);
  3730. }
  3731. function getSubject(){
  3732. return $this->subject();
  3733. }
  3734. function getBody(){
  3735. $content=$this->body();
  3736. if('HTML'===$this->is_html){
  3737. return $content['HTML']['CONTENT'];
  3738. }else{
  3739. return $content['TEXT']['CONTENT'];
  3740. }
  3741. }
  3742. function setMailer($type = 'mail', $options = array()){
  3743. switch ($type){
  3744. case 'smtp':
  3745. $this->smtp = true;
  3746. $this->sendmail = false;
  3747. $this->mailer = 'smtp';
  3748. if (isset($options['keep_alive'])){
  3749. $this->keepParameter(true);
  3750. }
  3751. break;
  3752. case 'sendmail':
  3753. $this->sendmail = true;
  3754. $this->smtp = false;
  3755. $this->mailer = 'sendmail';
  3756. break;
  3757. default:
  3758. $this->smtp = false;
  3759. $this->sendmail = false;
  3760. $this->mailer = 'mail';
  3761. break;
  3762. }
  3763. }
  3764. function getMailer(){
  3765. return $this->mailer;
  3766. }
  3767. function setSender($address, $name = null){
  3768. $this->addHeader( 'Return-Path' , $address );
  3769. }
  3770. function getSender(){
  3771. return isset($this->other_header['Return-Path']) ? $this->other_header['Return-Path']:null;
  3772. }
  3773. function setFrom($address, $name = null){
  3774. $this->from( $address , $name );
  3775. }
  3776. function addAddresses($addresses){
  3777. $this->to( $addresses , null , true );
  3778. }
  3779. function addAddress($address, $name = null){
  3780. $this->to( $address , $name , true );
  3781. }
  3782. function addCc($address, $name = null){
  3783. $this->cc( $address , $name , true );
  3784. }
  3785. function addBcc($address, $name = null){
  3786. $this->cc( $address , $name , true );
  3787. }
  3788. function addReplyTo($address, $name = null){
  3789. $this->replyto( $address , $name , true );
  3790. }
  3791. function clearAddresses(){
  3792. $this->to =array();
  3793. }
  3794. function clearCcs(){
  3795. $this->cc =array();
  3796. }
  3797. function clearBccs(){
  3798. $this->bcc =array();
  3799. }
  3800. function clearReplyTos(){
  3801. $this->replyto =array();
  3802. }
  3803. function clearAllRecipients(){
  3804. $this->clearAddresses();
  3805. $this->clearCcs();
  3806. $this->clearBccs();
  3807. $this->clearReplyTos();
  3808. }
  3809. function addAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream'){
  3810. return $this->attach(array('PATH'=>$path,'NAME'=>$name,'MIME-TYPE'=>$type),true);
  3811. }
  3812. function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream'){
  3813. return $this->attach(array('PATH'=>$path,'NAME'=>$name,'MIME-TYPE'=>$type,'CONTENT-ID'=>$cid),true);
  3814. }
  3815. function setAttachments($attachments){}
  3816. function clearAttachments(){
  3817. $this->attach=array();
  3818. }
  3819. function addCustomHeader($name, $value){
  3820. $this->addHeader($name, $value);
  3821. }
  3822. function clearCustomHeaders(){
  3823. $this->other_header=array();
  3824. }
  3825. function prepare(){}
  3826. function smtpClose(){}
  3827. function setDomain($hostname){}
  3828. function getDomain(){}
  3829. function setHostname($hostname){}
  3830. function getHostname(){}
  3831. function setPort($port){}
  3832. function getPort(){}
  3833. function setUsername($username){}
  3834. function getUsername(){}
  3835. function setPassword($password){}
  3836. function getPassword(){}
  3837. function setWordWrap($wordWrap){}
  3838. function getWordWrap(){}
  3839. }
  3840. class QdDeco{
  3841. var $template = null;
  3842. var $data = array();
  3843. function template( $template = null ){
  3844. if(is_null($template)){
  3845. return $this->template;
  3846. }
  3847. $this->template = trim(preg_replace("/\\r?\\n/is","\r\n",$template));
  3848. return true;
  3849. }
  3850. function get( $kind ){
  3851. if(!empty($this->data[$kind])){
  3852. return $this->data[$kind];
  3853. }
  3854. if('ATTACH'===$kind){
  3855. return array();
  3856. }else{
  3857. return null;
  3858. }
  3859. }
  3860. function decode(){
  3861. if(!class_exists('QdmailReceiver')){
  3862. include('qd_mail_receiver.php');
  3863. }
  3864. $num_boundary = strpos(strtolower($this->template),'boundary');
  3865. $num_crlf = strpos($this->template,"\r\n\r\n");
  3866. $template = $this->template;
  3867. while((false!==$num_boundary)&&(false!==$num_crlf)&&($num_boundary > $num_crlf)){
  3868. $template = substr($template,$num_crlf+4);
  3869. $num_crlf = strpos($template,"\r\n\r\n");
  3870. $num_boundary = strpos(strtolower($template),'boundary');
  3871. }
  3872. $receiver = QdmailReceiver::start( 'direct' , $template );
  3873. $this->data['HTML'] = $receiver->bodyAutoSelect() ;
  3874. if(false===$this->data['HTML']){
  3875. $this->data['HTML'] = '';
  3876. }
  3877. $attach = $receiver->attach();
  3878. foreach($attach as $att){
  3879. if(isset($att['content-id'])){
  3880. $cid = rtrim($att['content-id'],'>');
  3881. $cid = ltrim($cid,'<');
  3882. }elseif(isset($att['content_id'])){
  3883. $cid = rtrim($att['content_id'],'>');
  3884. $cid = ltrim($cid,'<');
  3885. }else{
  3886. $cid = null;
  3887. }
  3888. $this->data['ATTACH'][]=array(
  3889. 'PATH' => $att['filename_safe'],
  3890. 'NAME' => $att['filename_safe'],
  3891. 'CONTENT-TYPE' => $att['mimetype'],
  3892. 'CONTENT-ID' => $cid,
  3893. '_CHARSET' => null,
  3894. '_ORG_CHARSET' => null,
  3895. 'DIRECT' => $att['value'],
  3896. 'BARE' => false,
  3897. );
  3898. }
  3899. return true;
  3900. }
  3901. }?>