Example #1
0
 /**
  * Surcharge la méthode __toString() de la classe parente.
  * Signe et/ou chiffre l’email résultant à l’aide du programme GnuPG.
  * 
  * @access public
  * @return string
  */
 public function __toString()
 {
     if (!is_executable($this->gpg_bin)) {
         throw new Exception(sprintf("[%s] is not a valid executable.", $this->gpg_bin));
     }
     if (!(file_exists($this->logfile) && is_writable($this->logfile) || is_writable(dirname($this->logfile)))) {
         throw new Exception(sprintf("Unable to write log file [%s].", $this->logfile));
     }
     $tmpdir = escapeshellarg($this->tmpdir);
     $logfile = escapeshellcmd($this->logfile);
     $digest_algo = escapeshellarg($this->digest_algo);
     $gpg_cmd = escapeshellcmd($this->gpg_bin);
     $gpg_cmd .= " --no-verbose --no-tty --batch --textmode --armor" . " --always-trust --comment \"Using GnuPG with Wamailer\"";
     if (!is_null($this->homedir)) {
         $gpg_cmd .= sprintf(" --homedir %s", escapeshellarg($this->homedir));
     }
     /**
      * Les emails signés et/ou chiffrés doivent être restreints
      * aux caractères 7bit uniquement (us-ascii)
      * 
      * @see RFC 3156#3 - Content-Transfer-Encoding restrictions
      */
     if ($this->_sign || $this->_encrypt) {
         if (!is_null($this->_textPart)) {
             $this->_textPart->encoding = 'quoted-printable';
         }
         if (!is_null($this->_htmlPart)) {
             $this->_htmlPart->encoding = 'quoted-printable';
         }
     }
     parent::__toString();
     $headers = $this->headers_txt;
     $message = $this->message_txt;
     $tmpfile = tempnam($this->tmpdir, 'wa');
     file_put_contents($tmpfile, $message);
     //
     // Le message doit être chiffré (+ éventuellement signé)
     //
     if ($this->_encrypt) {
         if (!is_null($this->cipher_algo)) {
             $gpc_cmd .= sprintf(' --cipher-algo %s', escapeshellarg($this->cipher_algo));
         }
         if ($this->encryption == self::A_ENCRYPTION) {
             if (count($this->recipients) == 0) {
                 throw new Exception("No recipient specified!");
             }
             foreach ($this->recipients as $recipient) {
                 $gpg_cmd .= sprintf(' --recipient %s', escapeshellarg($recipient));
             }
             if ($this->_sign) {
                 if (!is_null($this->secretkey)) {
                     $gpg_cmd .= sprintf(" --local-user %s", escapeshellarg($this->secretkey));
                 }
                 if (!is_null($this->passphrase)) {
                     $gpg_cmd = sprintf("echo %s | %s --passphrase-fd 0", escapeshellarg($this->passphrase), $gpg_cmd);
                 }
                 $gpg_cmd = sprintf("%s --output - --digest-algo %s --encrypt --sign %s", $gpg_cmd, $digest_algo, escapeshellarg($tmpfile));
             } else {
                 $gpg_cmd = sprintf("%s --output - --encrypt %s", $gpg_cmd, escapeshellarg($tmpfile));
             }
         } else {
             $password = escapeshellarg($this->password);
             if ($this->_sign) {
                 if (!is_null($this->secretkey)) {
                     $gpg_cmd .= sprintf(" --local-user %s", escapeshellarg($this->secretkey));
                 }
                 $gpg_cmd = sprintf("echo %s | %s --passphrase-fd 0" . " --output - --digest-algo %s --symmetric --sign %s", $password, $gpg_cmd, $digest_algo, escapeshellarg($tmpfile));
             } else {
                 $gpg_cmd = sprintf("echo %s | %s --passphrase-fd 0" . " --output - --symmetric %s", $password, $gpg_cmd, escapeshellarg($tmpfile));
             }
         }
         exec("{$gpg_cmd} 2>{$logfile}", $output, $result);
         if ($result !== 0) {
             unlink($tmpfile);
             throw new Exception("Cannot encrypt email (GPG error)");
         }
         $encrypted_msg = implode("\r\n", $output);
         $gpg_sub1 = new Mime_Part();
         $gpg_sub1->headers->set('Content-Type', 'application/pgp-encrypted');
         $gpg_sub1->headers->set('Content-Description', 'PGP/MIME version identification');
         $gpg_sub1->body = 'Version: 1';
         $gpg_sub2 = new Mime_Part();
         $gpg_sub2->headers->set('Content-Type', 'application/octet-stream');
         $gpg_sub2->headers->get('Content-Type')->param('name', 'encrypted.asc');
         $gpg_sub2->headers->set('Content-Description', 'OpenPGP encrypted message');
         $gpg_sub2->headers->set('Content-Disposition', 'inline');
         $gpg_sub2->headers->get('Content-Disposition')->param('filename', 'encrypted.asc');
         $gpg_sub2->body = $encrypted_msg;
         $gpg_sub2->wraptext = false;
         //
         // Bloc MIME global
         //
         $gpg = new Mime_Part();
         $gpg->headers->set('Content-Type', 'multipart/encrypted');
         $gpg->headers->get('Content-Type')->param('protocol', 'application/pgp-encrypted');
         $gpg->body = 'This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)';
         $gpg->addSubPart($gpg_sub1);
         $gpg->addSubPart($gpg_sub2);
         $message = $gpg->__toString();
     } else {
         if ($this->_sign) {
             if (!is_null($this->secretkey)) {
                 $gpg_cmd .= sprintf(" --local-user %s", escapeshellarg($this->secretkey));
             }
             if (!is_null($this->passphrase)) {
                 $gpg_cmd = sprintf("echo %s | %s --passphrase-fd 0", escapeshellarg($this->passphrase), $gpg_cmd);
             }
             $gpg_cmd = sprintf("%s --output - --digest-algo %s --detach-sign %s", $gpg_cmd, $digest_algo, escapeshellarg($tmpfile));
             exec("{$gpg_cmd} 2>{$logfile}", $output, $result);
             if ($result !== 0) {
                 unlink($tmpfile);
                 throw new Exception("Cannot sign email (GPG error)");
             }
             $signature = implode("\r\n", $output);
             $gpg_sub = new Mime_Part();
             $gpg_sub->headers->set('Content-Type', 'application/pgp-signature');
             $gpg_sub->headers->get('Content-Type')->param('name', 'signature.asc');
             $gpg_sub->headers->set('Content-Description', 'OpenPGP digital signature');
             $gpg_sub->headers->set('Content-Disposition', 'attachment');
             $gpg_sub->headers->get('Content-Disposition')->param('filename', 'signature.asc');
             $gpg_sub->body = $signature;
             $gpg_sub->wraptext = false;
             //
             // Bloc MIME global
             //
             $gpg = new Mime_Part();
             $gpg->headers->set('Content-Type', 'multipart/signed');
             $gpg->headers->get('Content-Type')->param('micalg', "pgp-{$this->digest_algo}");
             $gpg->headers->get('Content-Type')->param('protocol', 'application/pgp-signature');
             $gpg->body = "This is an OpenPGP/MIME signed message (RFC 2440 and 3156).";
             $gpg->addSubPart($message);
             $gpg->addSubPart($gpg_sub);
             $message = $gpg->__toString();
         }
     }
     unlink($tmpfile);
     return $headers . $message;
 }
Example #2
0
 /**
  * Retourne l'email sous forme de chaîne formatée prète à l'envoi
  * 
  * @access public
  * @return string
  */
 public function __toString()
 {
     $this->headers->set('Date', date(DATE_RFC2822));
     $this->headers->set('MIME-Version', '1.0');
     $this->headers->set('Message-ID', sprintf('<%s@%s>', md5(microtime() . rand()), MAILER_HOSTNAME));
     $this->headers_txt = $this->headers->__toString();
     if (!empty($this->message_txt)) {
         return $this->headers_txt . $this->message_txt;
     }
     $rootPart = null;
     $attachParts = $this->_attachParts;
     if (!is_null($this->_htmlPart)) {
         $rootPart = $this->_htmlPart;
         if (!is_null($this->_textPart)) {
             $rootPart = new Mime_Part();
             $rootPart->addSubPart($this->_textPart);
             $rootPart->addSubPart($this->_htmlPart);
             $rootPart->headers->set('Content-Type', 'multipart/alternative');
         }
         $embedParts = array();
         foreach ($attachParts as &$attach) {
             if ($attach->headers->get('Content-ID') == null) {
                 $name = $attach->headers->get('Content-Type')->param('name');
                 $regexp = '/<([^>]+=\\s*)(["\'])cid:' . preg_quote($name, '/') . '\\2([^>]*)>/S';
                 if (!preg_match($regexp, $this->_htmlPart->body)) {
                     continue;
                 }
                 $cid = md5(microtime()) . '@' . MAILER_HOSTNAME;
                 $this->_htmlPart->body = preg_replace($regexp, '<\\1\\2cid:' . $cid . '\\2\\3>', $this->_htmlPart->body);
                 $attach->headers->set('Content-ID', "<{$cid}>");
             }
             array_push($embedParts, $attach);
             $attach = null;
         }
         if (count($embedParts) > 0) {
             $embedPart = new Mime_Part();
             $embedPart->addSubPart($rootPart);
             $embedPart->addSubPart($embedParts);
             $embedPart->headers->set('Content-Type', 'multipart/related');
             $embedPart->headers->get('Content-Type')->param('type', $rootPart->headers->get('Content-Type')->value);
             $rootPart = $embedPart;
         }
     } else {
         if (!is_null($this->_textPart)) {
             $rootPart = $this->_textPart;
         }
     }
     // filtrage nécessaire après la boucle de traitement des objets embarqués plus haut
     $attachParts = array_filter($attachParts);
     if (count($attachParts) > 0) {
         if (!is_null($rootPart)) {
             $mixedPart = new Mime_Part();
             $mixedPart->headers->set('Content-Type', 'multipart/mixed');
             $mixedPart->addSubPart($rootPart);
             $mixedPart->addSubPart($attachParts);
         } else {
             if (count($attachParts) == 1) {
                 $mixedPart = $attachParts[0];
             } else {
                 $mixedPart = new Mime_Part();
                 $mixedPart->headers->set('Content-Type', 'multipart/mixed');
                 $mixedPart->addSubPart($attachParts);
             }
         }
         $rootPart = $mixedPart;
     }
     //
     // Le corps d'un email est optionnel (cf. RFC 2822#3.5)
     //
     if (!is_null($rootPart)) {
         //
         // Par convention, un bref message informatif est ajouté aux emails
         // composés de plusieurs sous-parties, au cas où le client mail
         // ne supporterait pas ceux-ci…
         //
         if (strncasecmp($rootPart->headers->get('Content-Type')->value, 'multipart', 9) == 0) {
             $rootPart->body = "This is a multi-part message in MIME format.";
         }
         $this->message_txt = $rootPart->__toString();
     }
     return $this->headers_txt . $this->message_txt;
 }