📄 swift.php
字号:
public function addAttachment($data, $filename, $type='application/octet-stream') { $this->attachments[] = "Content-Type: $type; ". "name=\"$filename\";\r\n". "Content-Transfer-Encoding: base64\r\n". "Content-Description: $filename\r\n". "Content-Disposition: attachment; ". "filename=\"$filename\"\r\n\r\n". chunk_split($this->encode($data, 'base64')); } /** * Get the current number of attachments in the mail * @return int num attachments */ public function numAttachments() { return count($this->attachments); } /** * Insert an inline image and return it's name * These work like attachments but have a content-id * and are inline/related. * @param string path * @return string name */ public function addImage($path) { if (!file_exists($path)) return false; $gpc = ini_get('magic_quotes_gpc'); ini_set('magic_quotes_gpc', 0); $gpc_run = ini_get('magic_quotes_runtime'); ini_set('magic_quotes_runtime', 0); $img_data = @getimagesize($path); if (!$img_data) return false; $type = image_type_to_mime_type($img_data[2]); $filename = basename($path); $data = file_get_contents($path); $cid = 'SWM'.md5(uniqid(rand(), true)); $this->images[] = "Content-Type: $type\r\n". "Content-Transfer-Encoding: base64\r\n". "Content-Disposition: inline; ". "filename=\"$filename\"\r\n". "Content-ID: <$cid>\r\n\r\n". chunk_split($this->encode($data, 'base64')); ini_set('magic_quotes_gpc', $gpc); ini_set('magic_quotes_runtime', $gpc_run); return 'cid:'.$cid; } /** * Insert an inline file and return it's name * These work like attachments but have a content-id * and are inline/related. * The data is the file contents itself (binary safe) * @param string file contents * @param string content-type * @param string filename * @param string content-id * @return string name */ public function embedFile($data, $type='application/octet-stream', $filename=false, $cid=false) { if (!$cid) $cid = 'SWM'.md5(uniqid(rand(), true)); if (!$filename) $filename = $cid; $this->images[] = "Content-Type: $type\r\n". "Content-Transfer-Encoding: base64\r\n". "Content-Disposition: inline; ". "filename=\"$filename\"\r\n". "Content-ID: <$cid>\r\n\r\n". chunk_split($this->encode($data, 'base64')); return 'cid:'.$cid; } /** * Close the connection in the connecion object * @return void */ public function close() { if ($this->connection->writeHook && $this->isConnected()) { $this->command("QUIT\r\n"); $this->connection->stop(); } $this->triggerEventHandler('onClose'); } /** * Check if Swift has failed and stopped processing * @return bool failed */ public function hasFailed() { return $this->failed; } /** * Force Swift to fail and stop processing * @return void */ public function fail() { $this->failed = true; $this->triggerEventHandler('onFail'); } /** * Detect if a string contains multi-byte non-ascii chars that fall in the UTF-8 tanges * @param mixed input * @return bool */ public function detectUTF8($string_in) { foreach ((array)$string_in as $string) { if (is_array($string)) { if ($this->detectUTF8($string)) return true; } elseif (preg_match('%(?: [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte |\xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs |[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte |\xED[\x80-\x9F][\x80-\xBF] # excluding surrogates |\xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 |[\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 |\xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 )+%xs', $string)) return true; } return false; } /** * This function checks for 7bit *printable* characters * which excludes \r \n \t etc and so, is safe for use in mail headers * Actual permitted chars [\ !"#\$%&'\(\)\*\+,-\.\/0123456789:;<=>\?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\\\]\^_`abcdefghijklmnopqrstuvwxyz{\|}~] * Ranges \x00-\x1F are printer control sequences * \x7F is the ascii delete character * @param string input * @return bool */ public function is7bitPrintable($string) { if (preg_match('/^[\x20-\x7E]*$/D', $string)) return true; else return false; } /** * This is harsh! It makes things safe for sending as command sequences in SMTP * Specifically the enveloping. We could be extremely strict and implement what I planned on doing * here: http://www.swiftmailer.org/contrib/proposed-address-test.txt * @param string input * @return safe output */ public function make7bitPrintable($string) { return preg_replace('/[^\x20-\x7E]/', '', $string); } /** * Encode a string (mail) in a given format * Currently supports: * - BASE64 * - Quoted-Printable * - Ascii 7-bit * - Ascii 8bit * - Binary (not encoded) * * @param string input * @param string encoding * @return string encoded output */ public function encode($string, $type, $maxlen=false) { $type = strtolower($type); switch ($type) { case 'base64': return base64_encode($string); break; // case 'quoted-printable': return $this->quotedPrintableEncode($string, $maxlen); // case '7bit': case '8bit': break; case 'binary': default: break; } return $string; } /** * Headers cannot have non-ascii or high ascii chars in them * @param mixed input * @return string encoded output (with encoding type) */ public function safeEncodeHeader($string) { if (!is_array($string)) { if ($this->is7bitPrintable($string)) return $string; else { //Check if the string contains address notation $address_start = strrpos($string, '<'); $address_end = strrpos($string, '>'); $address = ''; //If the < and > are in the correct places if (($address_start !== false) && $address_start < $address_end) { //Then store the email address $address = substr($string, $address_start, ($address_end-$address_start+1)); if (!$this->is7bitPrintable($address)) $address = $this->make7bitPrintable($address); //... and remove it from the string $string = substr($string, 0, $address_start); } if ($this->headerEncoding == 'B') $encoded = trim(chunk_split($this->encode($string, 'base64'))); else { $this->headerEncoding = 'Q'; $encoded = trim($this->encode($string, 'quoted-printable')); } $lines = explode("\r\n", $encoded); return '=?'.$this->charset.'?'.$this->headerEncoding.'?'.implode("?=\r\n =?{$this->charset}?{$this->headerEncoding}?", $lines).'?= '.$address; } } else { $ret = array(); foreach ($string as $line) { $ret[] = $this->safeEncodeHeader($line); //Recurse } return $ret; } } /** * Handles quoted-printable encoding * From php.net by user bendi at interia dot pl * @param string input * @param int maxlength * @return string encoded output * @private */ private function quotedPrintableEncode($string, $maxlen=false) { if (!$maxlen) $maxlen = 73; $string = preg_replace('/[^\x21-\x3C\x3E-\x7E\x09\x20]/e', 'sprintf( "=%02x", ord ( "$0" ) ) ;', $string); preg_match_all('/.{1,'.$maxlen.'}([^=]{0,3})?/', $string, $matches); $sep = "=\r\n"; return implode($sep, $matches[0]); } /** * Converts lone LF characters to CRLF * @param string input * @return string converted output */ public function LFtoCRLF($string) { return preg_replace("@(?:(?<!\r)\n)|(?:\r(?!\n))@", "\r\n", $string); } /** * Prevents premature <CRLF>.<CRLF> strings * Converts any lone LF characters to CRLF * @param string input * @return string escaped output */ public function makeSafe($string) { return str_replace("\r\n.", "\r\n..", $this->LFtoCRLF($string)); } /** * Pulls an email address from a "Name" <add@ress> string * @param string input * @return string address */ public function getAddress($string) { if (!$string) return null; if (preg_match('/^.*?<([^>]+)>\s*$/s', $string, $matches)) { return '<'.$this->make7bitPrintable($matches[1]).'>'; } elseif (!preg_match('/<|>/', $string)) return '<'.$this->make7bitPrintable($string).'>'; else return $this->make7bitPrintable($string); } /** * Builds the headers needed to reflect who the mail is sent to * Presently this is just the "To: " header * @param string address * @return string headers * @private */ private function makeRecipientHeaders($address=false) { if ($address) return "To: ".$this->safeEncodeHeader($address)."\r\n"; else { $ret = "To: ".implode(",\r\n\t", $this->safeEncodeHeader($this->to))."\r\n"; if (!empty($this->Cc)) $ret .= "Cc: ".implode(",\r\n\t", $this->safeEncodeHeader($this->Cc))."\r\n"; return $ret; } } /** * Structure a given array of addresses into the 1-dim we want * @param array unstructured * @return array structured * @private */ private function parseAddressList($u_array) { $ret = array(); foreach ($u_array as $val) { if (is_array($val)) $ret[] = '"'.$val[0].'" <'.$val[1].'>'; else $ret[] = $val; } return $ret; } /** * Send an email using Swift (send commands) * @param string to_address * @param string from_address * @param string subject * @param string body, optional * @param string content-type,optional * @param string content-transfer-encoding,optional * @return bool successful */ public function send($to, $from, $subject, $body=false, $type='text/plain', $encoding=false) { if ((strtoupper($this->charset) != 'UTF-8') && $body && $this->detectUTF8($body) && !$this->userCharset) $this->charset = 'UTF-8'; if ((strtoupper($this->charset) != 'UTF-8') && $this->detectUTF8($subject) && !$this->userCharset) $this->charset = 'UTF-8'; if ((strtoupper($this->charset) != 'UTF-8') && $this->detectUTF8($to) && !$this->userCharset) $this->charset = 'UTF-8'; if ((strtoupper($this->charset) != 'UTF-8') && $this->detectUTF8($from) && !$this->userCharset) $this->charset = 'UTF-8'; if (!$encoding && $this->_8bitmime) $encoding = '8bit'; elseif (!$encoding) $encoding = 'quoted-printable'; $to = (array) $to; $this->to = $this->parseAddressList($to); //In these cases we just send the one email if ($this->useExactCopy || !empty($this->Cc) || !empty($this->Bcc)) { $this->currentMail = $this->buildMail(false, $from, $subject, $body, $type, $encoding, 1); $this->triggerEventHandler('onBeforeSend'); foreach ($this->currentMail as $command) { //Number of successful addresses expected $this->numAddresses = 1; if (is_array($command)) { //Commands can be returned as 1-dimensional arrays $this->numAddresses = count($command); foreach ($command as $c) { if (!$this->command($c)) { $this->logError('Sending failed on command: '.$c, 0); return false; } } } else if (!$this->command($command)) { $this->logError('Sending failed on command: '.$command, 0); return false; } } $this->triggerEventHandler('onSend'); } else { $get_body = true; $cached_body = ''; foreach ($this->to as $address) { $this->currentMail = $this->buildMail($address, $from, $subject, $body, $type, $encoding, $get_body); //If we have a cached version if (!$get_body) $this->currentMail[] = $this->makeRecipientHeaders($address).$cached_body; $this->triggerEventHandler('onBeforeSend'); foreach ($this->currentMail as $command) { //This means we're about to send the DATA part if ($get_body && ($this->responseCode == 354 || $this->responseCode == -1)) { $cached_body = $command; $command = $this->makeRecipientHeaders($address).$command; } if (is_array($command)) { foreach ($command as $c) { if (!$this->command($c)) { $this->logError('Sending failed on command: '.$c, 0); return false; } } } else if (!$this->command($command)) { $this->logError('Sending failed on command: '.$command, 0); return false; } } $this->triggerEventHandler('onSend'); $get_body = false; } } if ($this->autoFlush) $this->flush(true); //Tidy up a bit return true; } /** * Builds the list of commands to send the email * The last command in the output is the email itself (DATA) * The commands are as follows: * - MAIL FROM: <address> (0) * - RCPT TO: <address> (1) * - DATA (2) * - <email> (3) * * @param string to_address * @param string from_address * @param string subject * @param string body, optional * @param string content-type, optional * @param string encoding, optional * @return array commands * @private */ private function buildMail($to, $from, $subject, $body, $type='text/plain', $encoding='8bit', $return_data_part=true) { $date = date('r'); //RFC 2822 date $return_path = $this->returnPath ? $this->returnPath : $this->getAddress($from); $ret = array("MAIL FROM: ".$return_path."\r\n"); //Always //If the user specifies a different reply-to $reply_to = !empty($this->replyTo) ? $this->getAddress($this->replyTo) : $this->getAddress($from); //Standard headers $this->from = $from; $data = "From: ".$this->safeEncodeHeader($from)."\r\n". "Reply-To: ".$this->safeEncodeHeader($reply_to)."\r\n". "Subject: ".$this->safeEncodeHeader($subject)."\r\n". "Date: $date\r\n"; if ($this->readReceipt) $data .= "Disposition-Notification-To: ".$this->safeEncodeHeader($from)."\r\n"; if (!$to) //Only need one mail if no address was given { //We'll collate the addresses from the class properties $data .= $this->getMimeBody($body, $type, $encoding)."\r\n.\r\n"; $headers = $this->makeRecipientHeaders(); //Rcpt can be run several times $rcpt = array(); foreach ($this->to as $address) $rcpt[] = "RCPT TO: ".$this->getAddress($address)."\r\n"; foreach ($this->Cc as $address) $rcpt[] = "RCPT TO: ".$this->getAddress($address)."\r\n"; $ret[] = $rcpt; $ret[] = "DATA\r\n"; $ret[] = $headers.$this->headers.$data; //Bcc recipients get to see their own Bcc header but nobody else's foreach ($this->Bcc as $address) { $ret[] = "MAIL FROM: ".$this->getAddress($from)."\r\n"; $ret[] = "RCPT TO: ".$this->getAddress($address)."\r\n"; $ret[] = "DATA\r\n"; $ret[] = $headers."Bcc: ".$this->safeEncodeHeader($address)."\r\n".$this->headers.$data; } } else //Just make this individual email { if ($return_data_part) $mail_body = $this->getMimeBody($body, $type, $encoding); $ret[] = "RCPT TO: ".$this->getAddress($to)."\r\n"; $ret[] = "DATA\r\n"; if ($return_data_part) $ret[] = $data.$this->headers.$mail_body."\r\n.\r\n"; } return $ret; } /** * Returns the MIME-specific headers followed by the email * content as a string. * @param string body * @param string content-type * @param string encoding * @return string mime data * @private */ private function getMimeBody($string, $type, $encoding) { if ($string) //Not using MIME parts { $body = $this->encode($string, $encoding); if ($this->autoCompliance) $body = $this->chunkSplitLines($body); $data = "Content-Type: $type; charset=\"{$this->charset}\"; format=flowed\r\n". "Content-Transfer-Encoding: $encoding\r\n\r\n". $this->makeSafe($body); } else { //Build a full email from the parts we have $boundary = $this->getMimeBoundary(); $encoding = '8bit'; $mixalt = 'alternative'; $alternative_boundary = $this->getMimeBoundary(implode($this->parts)); if (!empty($this->images)) { $mixalt = 'mixed'; $related_boundary = $this->getMimeBoundary(implode($this->parts).implode($this->images)); $message_body = "Content-Type: multipart/related; ". "boundary=\"{$related_boundary}\"\r\n\r\n". "--{$related_boundary}\r\n"; $parts_body = "Content-Type: multipart/alternative; ". "boundary=\"{$alternative_boundary}\"\r\n\r\n". "--{$alternative_boundary}\r\n". implode("\r\n\r\n--$alternative_boundary\r\n", $this->parts). "\r\n--$alternative_boundary--\r\n"; $message_body .= $parts_body. "--$related_boundary\r\n"; $images_body = implode("\r\n\r\n--$related_boundary\r\n", $this->images); $message_body .= $images_body. "\r\n--$related_boundary--\r\n"; } else { if (!empty($this->attachments)) { $message_body = "Content-Type: multipart/alternative; ". "boundary=\"{$alternative_boundary}\"\r\n\r\n". "--{$alternative_boundary}\r\n". implode("\r\n\r\n--$alternative_boundary\r\n", $this->parts). "\r\n--$alternative_boundary--\r\n"; } else $message_body = implode("\r\n\r\n--$boundary\r\n", $this->parts); } if (!empty($this->attachments)) //Make a sub-message that contains attachment data { $mixalt = 'mixed'; $message_body .= "\r\n\r\n--$boundary\r\n". implode("\r\n--$boundary\r\n", $this->attachments); } $data = "MIME-Version: 1.0\r\n". "Content-Type: multipart/{$mixalt};\r\n". " boundary=\"{$boundary}\"\r\n". "Content-Transfer-Encoding: {$encoding}\r\n\r\n". "{$this->mimeWarning}\r\n". "--$boundary\r\n". "$message_body\r\n". "--$boundary--"; } return $data; }}?>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -