diff options
| -rw-r--r-- | etc/NEWS | 7 | ||||
| -rw-r--r-- | lisp/gnus/mml.el | 61 |
2 files changed, 58 insertions, 10 deletions
| @@ -276,6 +276,13 @@ for the ChangeLog file, if none already exists. Customize | |||
| 276 | built-in IDNA support now). | 276 | built-in IDNA support now). |
| 277 | 277 | ||
| 278 | --- | 278 | --- |
| 279 | *** When sending HTML messages with embedded images, and you have | ||
| 280 | exiftool installed, and you rotate images with EXIF data (i.e., | ||
| 281 | JPEGs), the rotational information will be inserted into the outgoing | ||
| 282 | image in the message. (The original image will not have its | ||
| 283 | orientation affected.) | ||
| 284 | |||
| 285 | --- | ||
| 279 | *** The 'message-valid-fqdn-regexp' variable has been removed, since | 286 | *** The 'message-valid-fqdn-regexp' variable has been removed, since |
| 280 | there are now top-level domains added all the time. Message will no | 287 | there are now top-level domains added all the time. Message will no |
| 281 | longer warn about sending emails to top-level domains it hasn't heard | 288 | longer warn about sending emails to top-level domains it hasn't heard |
diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el index 97cc87d06e3..eae4c61be82 100644 --- a/lisp/gnus/mml.el +++ b/lisp/gnus/mml.el | |||
| @@ -413,12 +413,21 @@ A message part needs to be split into %d charset parts. Really send? " | |||
| 413 | (setq contents (append (list (cons 'tag-location orig-point)) contents)) | 413 | (setq contents (append (list (cons 'tag-location orig-point)) contents)) |
| 414 | (cons (intern name) (nreverse contents)))) | 414 | (cons (intern name) (nreverse contents)))) |
| 415 | 415 | ||
| 416 | (defun mml-buffer-substring-no-properties-except-hard-newlines (start end) | 416 | (defun mml-buffer-substring-no-properties-except-some (start end) |
| 417 | (let ((str (buffer-substring-no-properties start end)) | 417 | (let ((str (buffer-substring-no-properties start end)) |
| 418 | (bufstart start) tmp) | 418 | (bufstart start) |
| 419 | (while (setq tmp (text-property-any start end 'hard 't)) | 419 | tmp) |
| 420 | (set-text-properties (- tmp bufstart) (- tmp bufstart -1) | 420 | ;; Copy over all hard newlines. |
| 421 | '(hard t) str) | 421 | (while (setq tmp (text-property-any start end 'hard t)) |
| 422 | (put-text-property (- tmp bufstart) (- tmp bufstart -1) | ||
| 423 | 'hard t str) | ||
| 424 | (setq start (1+ tmp))) | ||
| 425 | ;; Copy over all `display' properties (which are usually images). | ||
| 426 | (setq start bufstart) | ||
| 427 | (while (setq tmp (text-property-not-all start end 'display nil)) | ||
| 428 | (put-text-property (- tmp bufstart) (- tmp bufstart -1) | ||
| 429 | 'display (get-text-property tmp 'display) | ||
| 430 | str) | ||
| 422 | (setq start (1+ tmp))) | 431 | (setq start (1+ tmp))) |
| 423 | str)) | 432 | str)) |
| 424 | 433 | ||
| @@ -435,21 +444,21 @@ If MML is non-nil, return the buffer up till the correspondent mml tag." | |||
| 435 | (if (re-search-forward "<#\\(/\\)?mml." nil t) | 444 | (if (re-search-forward "<#\\(/\\)?mml." nil t) |
| 436 | (setq count (+ count (if (match-beginning 1) -1 1))) | 445 | (setq count (+ count (if (match-beginning 1) -1 1))) |
| 437 | (goto-char (point-max)))) | 446 | (goto-char (point-max)))) |
| 438 | (mml-buffer-substring-no-properties-except-hard-newlines | 447 | (mml-buffer-substring-no-properties-except-some |
| 439 | beg (if (> count 0) | 448 | beg (if (> count 0) |
| 440 | (point) | 449 | (point) |
| 441 | (match-beginning 0)))) | 450 | (match-beginning 0)))) |
| 442 | (if (re-search-forward | 451 | (if (re-search-forward |
| 443 | "<#\\(/\\)?\\(multipart\\|part\\|external\\|mml\\)." nil t) | 452 | "<#\\(/\\)?\\(multipart\\|part\\|external\\|mml\\)." nil t) |
| 444 | (prog1 | 453 | (prog1 |
| 445 | (mml-buffer-substring-no-properties-except-hard-newlines | 454 | (mml-buffer-substring-no-properties-except-some |
| 446 | beg (match-beginning 0)) | 455 | beg (match-beginning 0)) |
| 447 | (if (or (not (match-beginning 1)) | 456 | (if (or (not (match-beginning 1)) |
| 448 | (equal (match-string 2) "multipart")) | 457 | (equal (match-string 2) "multipart")) |
| 449 | (goto-char (match-beginning 0)) | 458 | (goto-char (match-beginning 0)) |
| 450 | (when (looking-at "[ \t]*\n") | 459 | (when (looking-at "[ \t]*\n") |
| 451 | (forward-line 1)))) | 460 | (forward-line 1)))) |
| 452 | (mml-buffer-substring-no-properties-except-hard-newlines | 461 | (mml-buffer-substring-no-properties-except-some |
| 453 | beg (goto-char (point-max))))))) | 462 | beg (goto-char (point-max))))))) |
| 454 | 463 | ||
| 455 | (defvar mml-boundary nil) | 464 | (defvar mml-boundary nil) |
| @@ -514,7 +523,9 @@ be \"related\" or \"alternate\"." | |||
| 514 | (when (search-forward (url-filename parsed) end t) | 523 | (when (search-forward (url-filename parsed) end t) |
| 515 | (let ((cid (format "fsf.%d" cid))) | 524 | (let ((cid (format "fsf.%d" cid))) |
| 516 | (replace-match (concat "cid:" cid) t t) | 525 | (replace-match (concat "cid:" cid) t t) |
| 517 | (push (list cid (url-filename parsed)) new-parts)) | 526 | (push (list cid (url-filename parsed) |
| 527 | (get-text-property start 'display)) | ||
| 528 | new-parts)) | ||
| 518 | (setq cid (1+ cid))))))) | 529 | (setq cid (1+ cid))))))) |
| 519 | ;; We have local images that we want to include. | 530 | ;; We have local images that we want to include. |
| 520 | (if (not new-parts) | 531 | (if (not new-parts) |
| @@ -527,11 +538,41 @@ be \"related\" or \"alternate\"." | |||
| 527 | (setq cont | 538 | (setq cont |
| 528 | (nconc cont | 539 | (nconc cont |
| 529 | (list `(part (type . "image/png") | 540 | (list `(part (type . "image/png") |
| 530 | (filename . ,(nth 1 new-part)) | 541 | ,@(mml--possibly-alter-image |
| 542 | (nth 1 new-part) | ||
| 543 | (nth 2 new-part)) | ||
| 531 | (id . ,(concat "<" (nth 0 new-part) | 544 | (id . ,(concat "<" (nth 0 new-part) |
| 532 | ">"))))))) | 545 | ">"))))))) |
| 533 | cont)))) | 546 | cont)))) |
| 534 | 547 | ||
| 548 | (defun mml--possibly-alter-image (file-name image) | ||
| 549 | (if (or (null image) | ||
| 550 | (not (consp image)) | ||
| 551 | (not (eq (car image) 'image)) | ||
| 552 | (not (image-property image :rotation)) | ||
| 553 | (not (executable-find "exiftool"))) | ||
| 554 | `((filename . ,file-name)) | ||
| 555 | `((filename . ,file-name) | ||
| 556 | (buffer | ||
| 557 | . | ||
| 558 | ,(with-current-buffer (mml-generate-new-buffer " *mml rotation*") | ||
| 559 | (set-buffer-multibyte nil) | ||
| 560 | (call-process "exiftool" | ||
| 561 | file-name | ||
| 562 | (list (current-buffer) nil) | ||
| 563 | nil | ||
| 564 | (format "-Orientation#=%d" | ||
| 565 | (cl-case (truncate | ||
| 566 | (image-property image :rotation)) | ||
| 567 | (0 0) | ||
| 568 | (90 6) | ||
| 569 | (180 3) | ||
| 570 | (270 8) | ||
| 571 | (otherwise 0))) | ||
| 572 | "-o" "-" | ||
| 573 | "-") | ||
| 574 | (current-buffer)))))) | ||
| 575 | |||
| 535 | (defun mml-generate-mime-1 (cont) | 576 | (defun mml-generate-mime-1 (cont) |
| 536 | (let ((mm-use-ultra-safe-encoding | 577 | (let ((mm-use-ultra-safe-encoding |
| 537 | (or mm-use-ultra-safe-encoding (assq 'sign cont)))) | 578 | (or mm-use-ultra-safe-encoding (assq 'sign cont)))) |