function DkimSigner::sign
File
-
vendor/
symfony/ mime/ Crypto/ DkimSigner.php, line 61
Class
- DkimSigner
- @author Fabien Potencier <fabien@symfony.com>
Namespace
Symfony\Component\Mime\CryptoCode
public function sign(Message $message, array $options = []) : Message {
$options += $this->defaultOptions;
if (!\in_array($options['algorithm'], [
self::ALGO_SHA256,
self::ALGO_ED25519,
], true)) {
throw new InvalidArgumentException(\sprintf('Invalid DKIM signing algorithm "%s".', $options['algorithm']));
}
$headersToIgnore['return-path'] = true;
$headersToIgnore['x-transport'] = true;
foreach ($options['headers_to_ignore'] as $name) {
$headersToIgnore[strtolower($name)] = true;
}
unset($headersToIgnore['from']);
$signedHeaderNames = [];
$headerCanonData = '';
$headers = $message->getPreparedHeaders();
foreach ($headers->getNames() as $name) {
foreach ($headers->all($name) as $header) {
if (isset($headersToIgnore[strtolower($header->getName())])) {
continue;
}
if ('' !== $header->getBodyAsString()) {
$headerCanonData .= $this->canonicalizeHeader($header->toString(), $options['header_canon']);
$signedHeaderNames[] = $header->getName();
}
}
}
[
$bodyHash,
$bodyLength,
] = $this->hashBody($message->getBody(), $options['body_canon'], $options['body_max_length']);
$params = [
'v' => '1',
'q' => 'dns/txt',
'a' => $options['algorithm'],
'bh' => base64_encode($bodyHash),
'd' => $this->domainName,
'h' => implode(': ', $signedHeaderNames),
'i' => '@' . $this->domainName,
's' => $this->selector,
't' => time(),
'c' => $options['header_canon'] . '/' . $options['body_canon'],
];
if ($options['body_show_length']) {
$params['l'] = $bodyLength;
}
if ($options['signature_expiration_delay']) {
$params['x'] = $params['t'] + $options['signature_expiration_delay'];
}
$value = '';
foreach ($params as $k => $v) {
$value .= $k . '=' . $v . '; ';
}
$value = trim($value);
$header = new UnstructuredHeader('DKIM-Signature', $value);
$headerCanonData .= rtrim($this->canonicalizeHeader($header->toString() . "\r\n b=", $options['header_canon']));
if (self::ALGO_SHA256 === $options['algorithm']) {
if (!openssl_sign($headerCanonData, $signature, $this->key, \OPENSSL_ALGO_SHA256)) {
throw new RuntimeException('Unable to sign DKIM hash: ' . openssl_error_string());
}
}
else {
throw new \RuntimeException(\sprintf('The "%s" DKIM signing algorithm is not supported yet.', self::ALGO_ED25519));
}
$header->setValue($value . ' b=' . trim(chunk_split(base64_encode($signature), 73, ' ')));
$headers->add($header);
return new Message($headers, $message->getBody());
}