使用PHP发送加密的电子邮件S / MIME

时间:2017-03-16 09:31:08

标签: php cakephp encryption digital-certificate smime

我一直在网上看很多,但我没有找到答案,是否可以使用PHP发送加密的电子邮件S / MIME?如果是的话,怎么样? (我正在使用cakephp 2.x)

非常感谢您提前

1 个答案:

答案 0 :(得分:0)

我设法使用PHPMailer找到了解决方案,它也适用于常规PHP。它会对电子邮件进行签名和加密,我无法找到与PHPMailer(签名和加密)签名的方法,所以我在class.phpmailer.php中添加了一些代码。在加密错误的情况下仍然需要添加一些错误处理,但到目前为止效果很好。

CakePHP 2.x的

下载PHPMailer并将其添加到您的Vendors文件夹(project_name / app / vendor)

在函数开头添加此行:

App::import('Vendor','PHPMailer/PHPMailerAutoload');

从这里对PHP或CakePHP也一样:

 $mail = new PHPMailer(); 
 $mail->setFrom('from_who@email', 'Intranet');
 //Set who the message is to be sent to 
 $mail->addAddress('to_who@email', 'Ricardo V'); 
 //Set the subject line 
 $mail->Subject = 'PHPMailer signing test';
 //Replace the plain text body with one created manually 
 $mail->Body = "some encrypted text...";
 //Attach an image file 
 $mail->addAttachment('D:/path_to_file/test.pdf'); 
 $mail->sign( 
     'app/webroot/cert/cert.crt', //The location of your certificate file 
     'app/webroot/cert/private.key', //The location of your private key
 file 
     'password', //The password you protected your private key with (not 
    //the Import Password! may be empty but parameter must not be omitted!) 
     'app/webroot/cert/certchain.pem', //the certificate chain.
     '1', //Encrypt the email as well, (1 = encrypt, 0 = dont encrypt)
     'app/webroot/cert/rvarilias.crt'//The location of public certificate 
   //to encrypt the email with.
 ); 
 if (!$mail->send()) { 
     echo "Mailer Error: " . $mail->ErrorInfo; 
 } else { 
     echo "Message sent!"; 
 } 

然后我们需要对class.phpmailer.php进行一些更改

用以下代码替换2368到2390之间的行:

$sign = @openssl_pkcs7_sign(
                    $file,
                    $signed,
                    'file://' . realpath($this->sign_cert_file),
                    array('file://' . realpath($this->sign_key_file), 
$this->sign_key_pass),
                    null,
                    PKCS7_DETACHED,
                    $this->sign_extracerts_file
                );
                if ($this->encrypt_file == 1) {
                    $encrypted = tempnam(sys_get_temp_dir(), 'encrypted');
                    $encrypt = @openssl_pkcs7_encrypt(
                    $signed,
                    $encrypted,
                    file_get_contents($this->encrypt_cert_file),
                    null,
                    0,
                    1
                );
                if ($encrypted) {
                    @unlink($file);
                    $body = file_get_contents($encrypted);
                    @unlink($signed);
                    @unlink($encrypted);
                    //The message returned by openssl contains both headers
and body, so need to split them up
                    $parts = explode("\n\n", $body, 2);
                    $this->MIMEHeader .= $parts[0] . $this->LE . $this->LE;
                    $body = $parts[1];
                } else {
                    @unlink($file);
                    @unlink($signed);
                    @unlink($encrypted);
                    throw new phpmailerException($this->lang('signing') .
openssl_error_string());
                }
                } else {

                if ($signed) {
                    @unlink($file);
                    $body = file_get_contents($signed);
                    @unlink($signed);
                    //The message returned by openssl contains both headers
 and body, so need to split them up
                    $parts = explode("\n\n", $body, 2);
                    $this->MIMEHeader .= $parts[0] . $this->LE . $this->LE;
                    $body = $parts[1];
            } else {
                    @unlink($file);
                    @unlink($signed);
                    throw new phpmailerException($this->lang('signing') .  
 openssl_error_string());
            }

                   } 

            }

然后寻找:

public function sign($cert_filename, $key_filename, $key_pass,   
$extracerts_filename = '')
{
    $this->sign_cert_file = $cert_filename;
    $this->sign_key_file = $key_filename;
    $this->sign_key_pass = $key_pass;
    $this->sign_extracerts_file = $extracerts_filename;
}

并将其更改为:

public function sign($cert_filename, $key_filename, $key_pass,
$extracerts_filename = '', $and_encrypt ='0', $encrypt_cert = '')
    {
        $this->sign_cert_file = $cert_filename;
        $this->sign_key_file = $key_filename;
        $this->sign_key_pass = $key_pass;
        $this->sign_extracerts_file = $extracerts_filename;
        $this->encrypt_file = $and_encrypt;
        $this->encrypt_cert_file = $encrypt_cert;
    }

寻找:

protected $sign_extracerts_file = '';

并在其后添加以下行:

protected $encrypt_cert = '';
protected $and_encrypt = '';

通过对phpmailer的这些更改,您可以发送已签名的电子邮件或已签名并加密的电子邮件。它也适用于附件。

我希望对某人有帮助。

*对于普通的PHP,不要添加以下行:

App::import('Vendor','PHPMailer/PHPMailerAutoload');