diff --git a/src/PHPMailerEnhanced/PHPMailerEnhanced.php b/src/PHPMailerEnhanced/PHPMailerEnhanced.php index eebcfe1..ef4acc3 100644 --- a/src/PHPMailerEnhanced/PHPMailerEnhanced.php +++ b/src/PHPMailerEnhanced/PHPMailerEnhanced.php @@ -19,6 +19,18 @@ class PHPMailerEnhanced extends PHPMailer { $this->CharSet = PHPMailer::CHARSET_UTF8; } + /** + * Generate a new cid, ensuring it don't already exist in the mail + * + * @return string The new cid + */ + public function cidGenerate (): string { + do { + $cid = uniqid('', true); + } while ($this->cidExists($cid)); + return $cid; + } + /** * @inheritDoc */ @@ -56,6 +68,61 @@ class PHPMailerEnhanced extends PHPMailer { return true; } + /** + * Add an attachment from a path on the filesystem. + * Never use a user-supplied path to a file! + * Returns false if the file could not be found or read. + * Explicitly *does not* support passing URLs; PHPMailer is not an HTTP client. + * If you need to do that, fetch the resource yourself and pass it in via a local file or string. + * + * @param string $path Path to the attachment + * @param string $name Overrides the attachment name + * @param string $encoding File encoding (see $Encoding) + * @param string $type MIME type, e.g. `image/jpeg`; determined automatically from $path if not specified + * @param string $disposition Disposition to use + * @param string|null $cid The attachment cid ; Null to use name (if provided) or filename. Use {@see static::cidGenerate()} to get a random cid + * + * @return bool True on successfully adding an attachment + * + * @throws Exception If an error occurs + */ + public function addAttachment ($path, $name = '', $encoding = self::ENCODING_BASE64, $type = '', $disposition = 'attachment', ?string $cid = null): bool { + if (!parent::addAttachment($path, $name, $encoding, $type, $disposition)) { + return false; + } + if ($cid !== null) { + $lastAttachment = &$this->attachment[array_key_last($this->attachment)]; + $lastAttachment[7] = $cid; + } + return true; + } + /** + * Add a string or binary attachment (non-filesystem). This method can be used to attach ascii or binary data, such as a BLOB record from a database. + * + * @param string $string String attachment data + * @param string $filename Name of the attachment + * @param string $encoding File encoding (see $Encoding) + * @param string $type File extension (MIME) type + * @param string $disposition Disposition to use + * @param string|null $cid The attachment cid ; Null to randomly generate one (see {@see static::cidGenerate()}) + * + * @return bool True on successfully adding an attachment + * + * @throws Exception If an error occurs + */ + public function addStringAttachment ($string, $filename, $encoding = self::ENCODING_BASE64, $type = '', $disposition = 'attachment', ?string $cid = null): bool { + if (!parent::addStringAttachment($string, $filename, $encoding, $type, $disposition)) { + return false; + } + + // Not sur why, but addStringAttachment force “0” as cid instead of generating one → force a random cid if not provided + $cid ??= $this->cidGenerate(); + $lastAttachment = &$this->attachment[array_key_last($this->attachment)]; + $lastAttachment[7] = $cid; + + return true; + } + /** * Process local files to embed then in mail * @@ -96,18 +163,12 @@ class PHPMailerEnhanced extends PHPMailer { return; } //endregion - //region Generate an unique “cid“ prefix - $cidNumber = 1; - do { - $cidPrefix = uniqid() . '_'; - } while ($this->cidExists($cidPrefix . $cidNumber)); - $embeddedImages = []; - //endregion //region Search all link (“src” or “href“ attribute) + $embeddedImages = []; $body = preg_replace_callback( '#(?<=src="|href=")[^"]+(?=")#i', - function (array $match) use ($localDirectory, $cidPrefix, &$cidNumber, &$embeddedImages): string { + function (array $match) use ($localDirectory, &$embeddedImages): string { $link = $match[0]; //region Check the link has no protocol (http, cid, etc.) or it's “file” @@ -133,8 +194,8 @@ class PHPMailerEnhanced extends PHPMailer { } //endregion - //region Associate a “cid“ to the file - $cid = $cidPrefix . ($cidNumber++); + //region Associate a cid to the file + $cid = $this->cidGenerate(); $embeddedImages[$cid] = $path; //endregion