A problem with showing embedded image was found in KMail program. KMail does not show an image if it has bad filename. I don't know if this problem exists in other email clients.
KMail fails to show an image
If the image has query string (for example, name looks like this: "product_image.jpg?q=aslfd"), this string will be concatenated with the filename, so the filename will be wrong for showing in KMail program. I think the reason of this behaviour is that the file "product_image.jpg?q=aslfd" has an unknown extension.

To improve this behaviour we just have to completely remove query string from addHTMLImage function calling.

This is the code before improvements have done:

      // Add the image and include any query string ($matches[5]) in the 3rd
      // "name" parameter. This enables compatibility with the token DoS fix
      // added in Drupal 7.20.
      && $this->addHTMLImage($path, NULL, $path . $matches[5])

This is the code after improvements have done:

     && $this->addHTMLImage($path, NULL, $path)

KMail shows image

Unfortunately, I can't find information about compatibility with the token DoS fix. I'll be glad if someone explain me this comment.

Attached patch should be applied after applying patches from #2525864: Searching for inline file references and attaching local files are not working with current pear Mail_Mime module from git and from #2526178: Embedded images are attached with wrong MIME types and bad names..

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

spuki’s picture

Issue summary: View changes
salvis’s picture

Issue summary: View changes

The line and the comment were added in #1929678: Mail MIME inline images using image_style's do not work with Drupal 7.20.

According to the drupal-7.20-release-notes the query string is needed for images with an image style. Removing the query string would break this functionality.

I guess other email clients don't have a problem with query strings in image URLs, so this looks like a bug in KMail.

spuki’s picture

I'm pretty sure that all drupal-7.20-release-notes are important when an image is loaded online from the site, but they're unsignificant when image is attached to some email message as a file.
I can't simulate situation, in which this query strings will be usefull.
Furthermore, if an email client has the feature "save attachement as", without query strings it will be easier to do.

salvis’s picture

Agreed, but why is this here then?

Is this used for both, embedded images and linked ones? Can we tell the difference?

Are you using embedded images only or did you get linked images to work, too?

After all, #1929678: Mail MIME inline images using image_style's do not work with Drupal 7.20 seems to have fixed an issue that came up with D7.20.

spuki’s picture

First of all, I found a mistake in my patch - it shouldn't work. But I've just developed a new version.

1. Function attachRegex is used only for embedded images.
2. Token is used for preventing creating styled images at the server automatically by an unauthorized user. In our case all images have already created and they will be attached to email letter. Therefore, token is absolutely useless. Furthermore, it breaks filename (in file system terminology filename is name and extension, extension '.png&q=salf' is ridiculous).
3. There is the another hypothetical mistake - several images with the same name (for example, images /tmp/folder/1.png and /tmp/folder2/1.png will be attached with the same name "1.png"). As I found, there are problems with such attachments in some cases.

New patch solve all problems in above list.

spuki’s picture

salvis’s picture

Thank you for the improved patch, spuki!

1. Function attachRegex is used only for embedded images.
2. Token is used for preventing creating styled images at the server automatically by an unauthorized user. In our case all images have already created and they will be attached to email letter. Therefore, token is absolutely useless.

But it did fix #1929678: Mail MIME inline images using image_style's do not work with Drupal 7.20! I fully understand that your patch fixes issues that need to be fixed, but I'm still wondering whether we won't resurrect that other issue.


3. There is the another hypothetical mistake - several images with the same name (for example, images /tmp/folder/1.png and /tmp/folder2/1.png will be attached with the same name "1.png"). As I found, there are problems with such attachments in some cases.

I see that this can be a problem, but it will need to be a separate patch. Otherwise the history gets confusing. Please create a new issue for that. To save some effort, I've already reviewed the new code below, so please take these comments into account in the separate patch.

  1. +++ b/mailmime.inc
    @@ -800,5 +801,61 @@ class MailMIME extends Mail_mime {
    +  ¶
    ...
    +  ¶
    ...
    +  ¶
    

    Remove the trailing spaces.

  2. +++ b/mailmime.inc
    @@ -800,5 +801,61 @@ class MailMIME extends Mail_mime {
    +   * @author Korotkov D. <dimakorotkov@mail.ru>
    ...
    +   * @author Korotkov D. <dimakorotkov@mail.ru>
    ...
    +   * @author Korotkov D. <dimakorotkov@mail.ru>
    

    Remove the @author tags, but add an empty line after the first line in the docblock, which should be in the third person and end with a dot, like "Gets a safe filename foe the image by path."

    See https://www.drupal.org/coding-standards/docs for information about how to write @param, @return, @var, etc. This is important, because API documentation is generated automatically from the docblocks, and even if it may not be perfect in existing code, we do our best to at least stick to it in new code. (docblock cleanup is welcome in separate issues, too, of course.)

  3. +++ b/mailmime.inc
    @@ -800,5 +801,61 @@ class MailMIME extends Mail_mime {
    +  {
    ...
    +    {
    ...
    +  {
    ...
    +    {
    ...
    +    {
    ...
    +    {
    ...
    +    {
    

    Opening braces must not be on a line of their own.
    https://www.drupal.org/coding-standards#controlstruct

  4. +++ b/mailmime.inc
    @@ -800,5 +801,61 @@ class MailMIME extends Mail_mime {
    +  protected $postfixes = array();
    ...
    +  protected function safe_filename($path)
    ...
    +  protected function postfix($path, $file)
    

    Names of class methods should typically start with a verb and use lower-case camelCase rather than underscores.

    See https://www.drupal.org/node/608152#naming or just follow the example of the existing code.

salvis’s picture

Status: Needs review » Needs work
spuki’s picture

FileSize
994 bytes

As I read in release notes, images styles tokens was introduced in Drupal 7.20. In previous Drupal versions the $matches argument of the attachRegex function doesn't contain the key #5, but now this argument is passed with this key, which contains the image style token. Due to this key the attachRegex function returns the path with the token, but the addHTMLImage function is called without this token, and the image is not correctly embedded.

  /**
   * A preg_replace_callback used to attach local files, if possible.
   *
   * @see get()
   */
  protected function attachRegex($matches) {
    if ( ($url = drupal_strip_dangerous_protocols(urldecode($matches[4])))
      && ($path = url_to_realpath($url))
      && is_file($path)
      && $this->addHTMLImage($path, NULL, $path)
    ) {
      // The parent method will replace this with the actual cid: string.
      $matches[4] = $path;
    }
    return implode('', array_slice($matches, 1));
  }

So, there is at least two ways for solving the problem. First way was described previously here: #1929678: Mail MIME inline images using image_style's do not work with Drupal 7.20.

  /**
   * A preg_replace_callback used to attach local files, if possible.
   *
   * @see get()
   */
  protected function attachRegex($matches) {
    if ( ($url = drupal_strip_dangerous_protocols(urldecode($matches[4])))
      && ($path = url_to_realpath($url))
      && is_file($path)
      // Add the image and include any query string ($matches[5]) in the 3rd
      // "name" parameter. This enables compatibility with the token DoS fix
      // added in Drupal 7.20.
      && $this->addHTMLImage($path, NULL, $path . $matches[5])
    ) {
      // The parent method will replace this with the actual cid: string.
      $matches[4] = $path;
    }
    return implode('', array_slice($matches, 1));
  }

The other obvios way is to ignore token (i.e. the key #5 in $matches argument) in embedded images. As for me, this way is more accurate, because it keeps correct filenames in attachments. All we need to do is to unset the key #5 in the $matches array.

  /**
   * A preg_replace_callback used to attach local files, if possible.
   *
   * @see get()
   */
  protected function attachRegex($matches) {
    if ( ($url = drupal_strip_dangerous_protocols(urldecode($matches[4])))
      && ($path = url_to_realpath($url))
      && is_file($path)
      && $this->addHTMLImage($path, NULL, $path)
    ) {
      // The parent method will replace this with the actual cid: string.
      $matches[4] = $path;
      // Remove any query string for keeping the correct file name in the 
      // attachment. This enables compatibility with the token DoS fix added in 
      // Drupal 7.20.
      unset($matches[5]);
    }
    return implode('', array_slice($matches, 1));
  }

What about images with the same name - I'll try to take into account your advice (thank you for it!) and probably I'll create new issue, maybe for the pear module, because this error may occurs not only in drupal MailMime module. I checked the behaviour of several email clients - all of them processes this situation successfully (KMail too).

spuki’s picture

Status: Needs work » Needs review
salvis’s picture

Status: Needs review » Closed (outdated)

It seems that spuki/KMail is alone with experiencing this issue, and committing this has the potential to cause more problems than it solves.

Maybe KMail has learned to strip query strings by now?

(Query strings are a common method for nudging browsers into refreshing cached images. I would expect email clients to behave accordingly.)