0

Today I got scared after noticing how many Microsoft ATP Safelinks had made their way into my org-mode calendar file. Therefore, is it possible to create a URL decoder to bypass Microsoft Safelinks for mu4e(gnus)? There are implementations for other mail-clients in Python? and Javascript but elisp (if possible) would be preferable. I am using mu4e 1.4.1 and emacs 26.3. Thanks in advance.

Update:

Thanks wasamasa. To wire it up to mu4e I've developed a url reader (below), based on this answer.

1

I've ported the Python code you've linked:

(require 'url-parse)

(defun my-decode-safelink (url)
  (if (string-match-p (regexp-quote "safelinks.protection.outlook.com") url)
      (let* ((query (url-filename (url-generic-parse-url url)))
             (url (cadr (assoc "/?url" (url-parse-query-string query))))
             (path (url-unhex-string url)))
        (replace-regexp-in-string (rx "/" (>= 20 (any "#$%&*^@"))) "" path))
    url))

(my-decode-safelink "https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Foffice.memoriesflower.com%2FPermission%2F%2525%2524%255E%2526%2526*%2523%2523%255E%2524%2525%255E%2526%255E*%2526%2523%255E%2525%2525%2526%2540%255E*%2523%2526%255E%2525%2523%2526%2540%2525*%255E%2540%255E%2523%2525%255E%2540%2526%2525*%255E%2540%2Foffice.php&data=01%7C01%7Cdavid.levin%40mheducation.com%7C0ac9a3770fe64fbb21fb08d50764c401%7Cf919b1efc0c347358fca0928ec39d8d5%7C0&sdata=PEoDOerQnha%2FACafNx8JAep8O9MdllcKCsHET2Ye%2B4%3D&reserved=0")
;; "https://office.memoriesflower.com/Permission/office.php"

(my-decode-safelink "https://office.memoriesflower.com/Permission/office.php")

;; "https://office.memoriesflower.com/Permission/office.php"

That leaves the part of wiring it up to mu4e.

| improve this answer | |
0

This is my answer. It works flawlessly. I hope it turns out to be useful. It is based on code from Wasamasa and Joseph Gay.

Update I've made it more generic, so that it works both in mu4e-view and mu4e-compose mode.

(require 'url-parse)
(defun my-decode-safelink (url)
  (if (string-match-p (regexp-quote "safelinks.protection") url)      
      (let* ((query (url-filename (url-generic-parse-url url)))
         (url (cadr (assoc "/?url" (url-parse-query-string query))))
         (path (url-unhex-string url)))
    (replace-regexp-in-string (rx "/" (>= 20 (any "#$%&*^@"))) "" path))
    url))

(defun unsafelinks (vmode)
  "This function filters MS safelinks from a message buffer"
  (interactive)
  (let ((simple-url-regexp "https?://") urls)
    (save-excursion
      ;; edit text URLs
      (while (search-forward-regexp simple-url-regexp nil t)
    (when-let ((url (thing-at-point 'url))
           (bounds (thing-at-point-bounds-of-url-at-point)))
      (delete-region (car bounds) (cdr bounds))
      (insert (my-decode-safelink url))))
      ;; edit widget URLs
      (beginning-of-buffer)
      (while (not (eobp)) 
    (goto-char (next-overlay-change (point)))
    (when-let (link (get-text-property (point) 'shr-url))             
      (and (string-match simple-url-regexp link) 
           ;; change overlay url echo
           (when (overlay-put (car (overlays-at (point))) 'help-echo (my-decode-safelink link)) t)
           ;; change url text-properties 
           (add-text-properties (point) (next-overlay-change (point)) (list 'shr-url (my-decode-safelink link) 'help-echo (my-decode-safelink link))) 
           ))
    (goto-char (next-overlay-change (point))))
      (when vmode (gnus-article-prepare-display)
        (set-buffer-modified-p nil)
        (read-only-mode)))))

;; Append it to mu4e view and compose mode hooks
(add-hook 'mu4e-view-mode-hook (lambda () (unsafelinks t)) t)
(add-hook 'mu4e-compose-mode-hook (lambda () (unsafelinks nil)) t)

Update

It is not 100% flawless, as sometimes backslashes are not captured by thing-at-point-bounds-of-url-at-point. A possible solution is to redefine the function as per this separate answer

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.