ソースを参照

Forward port of email fixes in 2.x

Mark Scherer 10 年 前
コミット
dfd3219099
2 ファイル変更56 行追加28 行削除
  1. 28 3
      src/Mailer/Email.php
  2. 28 25
      tests/TestCase/Mailer/EmailTest.php

+ 28 - 3
src/Mailer/Email.php

@@ -234,6 +234,8 @@ class Email extends CakeEmail {
 		if (empty($name)) {
 			$name = basename($file);
 		}
+
+		$name = pathinfo($name, PATHINFO_FILENAME) . '_' . md5($file) . '.' . pathinfo($name, PATHINFO_EXTENSION);
 		if ($contentId === null && ($cid = $this->_isEmbeddedAttachment($file, $name))) {
 			return $cid;
 		}
@@ -269,6 +271,12 @@ class Email extends CakeEmail {
 			$ext = pathinfo($filename, PATHINFO_EXTENSION);
 			$mimeType = $this->_getMimeByExtension($ext);
 		}
+
+		$filename = pathinfo($filename, PATHINFO_FILENAME) . '_' . md5($content) . '.' . pathinfo($filename, PATHINFO_EXTENSION);
+		if ($contentId === null && ($cid = $this->_isEmbeddedBlobAttachment($content, $filename))) {
+			return $cid;
+		}
+
 		$options['data'] = $content;
 		$options['mimetype'] = $mimeType;
 		$options['contentId'] = $contentId ? $contentId : str_replace('-', '', Text::uuid()) . '@' . $this->_domain;
@@ -287,16 +295,33 @@ class Email extends CakeEmail {
 	 *
 	 * @param string $file
 	 * @param string $name
-	 * @return bool|string Cid of the found file or false if no such attachment can be found
+	 * @return bool|string CID of the found file or false if no such attachment can be found
 	 */
 	protected function _isEmbeddedAttachment($file, $name) {
 		foreach ($this->_attachments as $filename => $fileInfo) {
 			if ($filename !== $name) {
 				continue;
 			}
-			if ($fileInfo['file'] === $file) {
-				return $fileInfo['contentId'];
+			return $fileInfo['contentId'];
+		}
+		return false;
+	}
+
+	/**
+	 * Returns if this particular file has already been attached as embedded file with this exact name
+	 * to prevent the same image to overwrite each other and also to only send this image once.
+	 * Allows multiple usage of the same embedded image (using the same cid)
+	 *
+	 * @param string $content
+	 * @param string $name
+	 * @return bool|string CID of the found file or false if no such attachment can be found
+	 */
+	protected function _isEmbeddedBlobAttachment($content, $name) {
+		foreach ($this->_attachments as $filename => $fileInfo) {
+			if ($filename !== $name) {
+				continue;
 			}
+			return $fileInfo['contentId'];
 		}
 		return false;
 	}

+ 28 - 25
tests/TestCase/Mailer/EmailTest.php

@@ -240,16 +240,15 @@ class EmailTest extends TestCase {
 		$this->assertContains('@' . env('HTTP_HOST'), $cid);
 
 		$res = $this->Email->getProtected('attachments');
-		$this->assertTrue(!empty($res['hotel.png']['file']));
-		unset($res['hotel.png']['file']);
+		$this->assertSame(1, count($res));
+
+		$image = array_shift($res);
 		$expected = [
-			'hotel.png' => [
-				//'file' => $file,
-				'mimetype' => 'image/png',
-				'contentId' => $cid
-			]
+			'file' => $file,
+			'mimetype' => 'image/png',
+			'contentId' => $cid
 		];
-		$this->assertSame($expected, $res);
+		$this->assertSame($expected, $image);
 	}
 
 	/**
@@ -306,20 +305,21 @@ html-part
 		$this->Email = new TestEmail();
 		$this->Email->emailFormat('both');
 		$cid = $this->Email->addEmbeddedBlobAttachment(file_get_contents($file), 'my_hotel.png');
+		$cid2 = $this->Email->addEmbeddedBlobAttachment(file_get_contents($file), 'my_hotel.png');
 
 		$this->assertContains('@' . env('HTTP_HOST'), $cid);
 
 		$res = $this->Email->getProtected('attachments');
-		$this->assertTrue(!empty($res['my_hotel.png']['data']));
-		unset($res['my_hotel.png']['data']);
+		$this->assertSame(1, count($res));
+
+		$images = $res;
+		$image = array_shift($images);
+		unset($image['data']);
 		$expected = [
-			'my_hotel.png' => [
-				//'data' => file_get_contents($file),
-				'mimetype' => 'image/png',
-				'contentId' => $cid,
-			]
+			'mimetype' => 'image/png',
+			'contentId' => $cid,
 		];
-		$this->assertEquals($expected, $res);
+		$this->assertEquals($expected, $image);
 
 		$options = [
 			'contentDisposition' => true,
@@ -328,15 +328,18 @@ html-part
 		$this->Email->addEmbeddedBlobAttachment(file_get_contents($file), 'my_other_hotel.png', 'image/jpeg', $cid, $options);
 
 		$res = $this->Email->getProtected('attachments');
-		$this->assertTrue(!empty($res['my_other_hotel.png']['data']));
-		unset($res['my_other_hotel.png']['data']);
-		$expected = [
-			'contentDisposition' => true,
-			//'data' => file_get_contents($file),
-			'mimetype' => 'image/jpeg',
-			'contentId' => $cid,
-		];
-		$this->assertEquals($expected, $res['my_other_hotel.png']);
+		$this->assertSame(2, count($res));
+
+		$keys = array_keys($res);
+		$keyLastRecord = $keys[count($keys) - 1];
+		$this->assertSame('image/jpeg', $res[$keyLastRecord]['mimetype']);
+		$this->assertTrue($res[$keyLastRecord]['contentDisposition']);
+
+		$cid3 = $this->Email->addEmbeddedBlobAttachment(file_get_contents($file) . 'xxx', 'my_hotel.png');
+		$this->assertNotSame($cid3, $cid);
+
+		$res = $this->Email->getProtected('attachments');
+		$this->assertSame(3, count($res));
 	}
 
 	/**