zoukankan      html  css  js  c++  java
  • php字符串处理(邮件处理)

    今日做单据邮件提醒功能,发现系统发出的邮件总是显示不全。调用发送邮件方法前记录下来的日志是完全的。
    经查询原来是邮件格式对邮件单行有长度限制:

    ps1:邮件字符限制

    本标准对行字符数量有2种限制。每行字符数必须(MUST)不超过998个,应该(SHOULD)不超过78个,
    除了CRLF。

    ps2:邮件正文换行符规定

      邮件正文一般由US-ASCII字符组成的多行文字。只有2个限制,如下:
      -CR,LF必须同时出现为CRLF,他们不可以分开出现在正文里。
      -正文的每行字符数必须(MUST)不超过998个,应该(SHOULD)不超过78个,除了CRLF。


    (原文链接):http://hi.baidu.com/zhufangtian/item/ba54cb5f09780413abf6d74b

    所以在发送邮件时必须对邮件字符串进行换行处理

       开始尝试用php substr() 函数按长度截断字符串换行,因为邮件正文里有很多html标签,在仅判断固定长度字符情况下,将很多标签组合截断(如<td> 在t和d之间截断换行了 ),所以原有的html标签被拆断了,破坏了原意,导致显示异常。

         后来测试codeigniter框架邮件发送插件,发现它支持这种单行超长邮件的发送,于是查看源码。分析其邮件正文处理方法,

    最终处理步骤:

    1.将字符串全部转化为小写

    2.将回车换行符替换为<br>。因为本项目邮件为html格式的

    3.去除多余空格

    4.替换a标签内容,防止标签内容超长被截断

    5.wordwrap方法处理字符串自动换行。()

    在实际项目中发现换行符必须为\r\n(在windows情况下实际测试,网上很多都说为\n\r,个人感觉是说错了),所以必须要规定wordwrap方法的替换参数,注意在替换格式后添加空格是为了有些邮件客户端(outlook)可以正常解析换行的属性标签,有些则不能(foxmail) 

    如截断后标签换行 tr和span中间有换行符,无空格。

    <tr
    span='3'>
    6.替换回a标签内容


    ps1:改造后邮件处理方法

    //邮件文本替换
    function __mailreplace($content, $type) {
    	//替换回车换行符(注意替换字符串后添加 空格,以便在wordwrap方法中可以将字符串换行)
    	if (strtolower ( $type ) == "html") {
    		$content = ltrim ( $content );
    		$content = str_replace ( array ('\n', '\r\n' ), "<br/> ", $content );
    		$content = str_replace ( array (chr ( 13 ), chr ( 13 ) . chr ( 10 ) ), "<br/> ", $content );
    		//替换空格
    		$content = str_replace ( " ", " ", $content );
    		//处理表格过长问题,将每行换行
    		$content = str_replace ( "</tr>", "</tr> ", $content );
    	} else {
    		$content = str_replace ( array ("<br>", "<br/>" ), "\r\n", $content );
    		$content = str_replace ( " ", " ", $content );
    	}
    	
            //替换多余空格
    	$content = preg_replace ( "| +|", " ", $content );
    	
    	//替换a标签(防止链接过长被截断)
    	$unwrap = array ();
    	if (preg_match_all ( '|(<a.*>.*</a>)|U', $content, $matches )) {
    		for($i = 0; $i < count ( $matches ['0'] ); $i ++) {
    			$unwrap [] = $matches ['1'] [$i];
    			$content = str_replace ( $matches ['1'] [$i], "{{a-link" . $i . "}}", $content );
    		}
    	}
    	//过长字符串自动换行(添加空格,避免html标签内属性换行时无法正常解析)
    	$content = wordwrap ( $content, 75, "\r\n ", FALSE );
    			
    	//替换回a标签
    	if (count ( $unwrap ) > 0) {
    		foreach ( $unwrap as $key => $val ) {
    			$content = str_replace ( "{{a-link" . $key . "}}", $val, $content );
    		}
    	}
    	return $content;
    }

    ps3:codeigniter源码:

    public function word_wrap($str, $charlim = '') {
      // Se the character limit
      if ($charlim == '') {
       $charlim = ($this->wrapchars == "") ? "76" : $this->wrapchars;
      }
      
      // Reduce multiple spaces  去除多余空格
      $str = preg_replace ( "| +|", " ", $str );
      
      // Standardize newlines  替换回车 换行符
      
      if (strpos ( $str, "\r" ) !== FALSE) {
       $str = str_replace ( array ("\r\n", "\r" ), "\n", $str );
      }
      
      // If the current word is surrounded by {unwrap} tags we'll
      // strip the entire chunk and replace it with a marker. 批量替换特定标签(改为批量替换a链接)
      $unwrap = array ();
      if (preg_match_all ( "|(\{unwrap\}.+?\{/unwrap\})|s", $str, $matches )) {
       for($i = 0; $i < count ( $matches ['0'] ); $i ++) {
        $unwrap [] = $matches ['1'] [$i];
        $str = str_replace ( $matches ['1'] [$i], "{{unwrapped" . $i . "}}", $str );
       }
      }
      
      // Use PHP's native public function to do the initial wordwrap.
      // We set the cut flag to FALSE so that any individual words that are
      // too long get left alone.  In the next step we'll deal with them.
      // 截断字符串
      $str = wordwrap ( $str, $charlim, "\n", FALSE );
      
      // Split the string into individual lines of text and cycle through them
      $output = "";
      foreach ( explode ( "\n", $str ) as $line ) {
       // Is the line within the allowed character count?
       // If so we'll join it to the output and continue
       if (strlen ( $line ) <= $charlim) {
        $output .= $line . $this->newline;
        continue;
       }
       
       $temp = '';
       while ( (strlen ( $line )) > $charlim ) {
        // If the over-length word is a URL we won't wrap it
        if (preg_match ( "!\[url.+\]|://|wwww.!", $line )) {
         break;
        }
        
        // Trim the word down
        $temp .= substr ( $line, 0, $charlim - 1 );
        $line = substr ( $line, $charlim - 1 );
       }
       // If $temp contains data it means we had to split up an over-length
       // word into smaller chunks so we'll add it back to our current line
       if ($temp != '') {
        $output .= $temp . $this->newline . $line;
       } else {
        $output .= $line;
       }
       $output .= $this->newline;
      }
      // Put our markers back
      // 将替换字符串替换回来
      if (count ( $unwrap ) > 0) {
       foreach ( $unwrap as $key => $val ) {
        $output = str_replace ( "{{unwrapped" . $key . "}}", $val, $output );
       }
      }
      return $output;
     }




  • 相关阅读:
    docker 的官方PHP镜像 如何修改 php.ini 配置
    数据结构和算法
    接口的幂等性
    linux ftp服务器设置,只允许用户访问指定的文件夹,禁止访问其他文件夹
    rabitmq + php
    微信上传客服消息图片
    golang Printf 函数有超过 10 个转义字符
    golang bufio.NewScarme
    springboot(一)
    springboot加入第三方jar,使用mvn打包
  • 原文地址:https://www.cnblogs.com/y0umer/p/3838870.html
Copyright © 2011-2022 走看看