• בלוג
  • לעשות את האימייל נפלא שוב

לעשות את האימייל נפלא שוב

אימייל הוא כנראה אחד המקומות בהם אנחנו מבלים הכי הרבה זמן (אולי חוץ מה IDE, לחלקנו אפילו יותר מה IDE), ובכל זאת רוב הזמן אנחנו מוכנים להשלים עם אפליקציות אימייל בינוניות או אפילו מרושעות. הדרך הנפוצה ביותר לקרוא אימייל היא ממשק הווב של אתרי המייל ובמיוחד ג'ימייל.

החיסרון המרכזי בגישה זו הוא שחייבים חיבור לאינטרנט כדי לקרוא ולכתוב מיילים או להסתכל בהודעות ישנות.

חיסרון שני בגישה הוא שאנחנו תקועים עם הממשק וחיבור המקשים שג'ימייל בחרו בשבילנו.

חיסרון שלישי הוא המעקב של ג'ימייל והצגת הפירסומות בתוך תיבת המייל כשאנחנו מנסים להתרכז בעבודה.

וחיסרון רביעי הוא שגוגל יכולה בכל רגע לנעול לנו את החשבון וכך בשניה איבדנו את כל הודעות הדוא"ל הישנות וכמובן שאין שם עם מי לדבר.

כל ספקי הדוא"ל תומכים כבר תקופה מאוד ארוכה בממשק סינכרון שנקרא imap. בממשק זה אתם מקבלים עותק של כל הודעות הדואר והתיקיות משרת המייל אליכם למחשב, אתם יכולים לעדכן את המיילים מקומית במערכת הקבצים ואז לסנכרן חזרה לשרת כדי שהשינויים שלכם יעודכנו גם שם. המדריך שאציג כאן בפוסט יאפשר לכם:

  1. לשמור עותק של כל המיילים אצלכם על המכונה

  2. לקרוא ולכתוב אימייל דרך תוכנת דואר משורת הפקודה שנקראת mutt

  3. לחפש בהודעות דואר ואנשי קשר גם כשאתם לא מחוברים לרשת משורת הפקודה באמצעות mu

1. שמירת כל העותקים של המיילים אלינו למכונה עם mbsync

התוכנה הראשונה ברשימה שלנו נקראת mbsync ויש לה תפקיד פשוט: היא מתחברת לשרת imap, מורידה משם את כל המיילים אליכם למכונה, ואם בתיקיית המיילים יש דברים חדשים גם שולחת בחזרה לשרת את השינויים.

החבילה ב Ubuntu נקראת isync ומתקינים אותה עם:

sudo apt-get install isync

ויש גם במק עם הומברו:

brew install isync

ל mbsync יש קובץ קונפיגורציה בשם ~/.mbsyncrc שכולל את כל הפרטים של השרת. כך נראית הקונפיגורציה אצלי (הסיסמאות מחוקות כמובן) שמתחבר לשרת דואר של fastmail. אפשר למצוא בקלות ברשת הגדרות דומות ל gmail:

# First section: remote IMAP account
IMAPAccount fastmail
Host imap.fastmail.com
Port 993
User YOUR_EMAIL_ADDRESS
Pass YOUR_PASSWORD
SSLType IMAPS
SSLVersions TLSv1.2

IMAPStore fastmail-remote
Account fastmail

# This section describes the local storage
MaildirStore fastmail-local
Path ~/Maildir/
Inbox ~/Maildir/INBOX
# The SubFolders option allows to represent all
# IMAP subfolders as local subfolders
SubFolders Verbatim

# This section a "channel", a connection between remote and local
Channel fastmail
Master :fastmail-remote:
Slave :fastmail-local:
Patterns *
Expunge slave
CopyArrivalDate yes
Sync All
Create Slave
SyncState *

המידע החשוב הוא שם המשתמש והסיסמה והתיקיה אליה שומרים את המיילים, בהגדרות שלי זו ~/Maildir.

אחרי התקנה ראשונית ויצירת קובץ ההגדרות נסו להריץ את הפקודה:

$ mbsync fastmail

כדי להפעיל את הסינכרון הראשוני ולראות שהכל עובד.

(הפרמטר הוא שם הערוץ כלומר המילה שבאה אחרי הפקודה Channel. במקרה של ג'ימייל כנראה שתרצו לעדכן את הקובץ וגם את שם הערוץ בהפעלת הפקודה).

2. יצירה ועדכון אינדקס לכל המיילים עם mu

הכלי הבא ברשימה נקרא mu והוא פשוט יודע לקרוא את המיילים שלכם, לסמן לעצמו דברים חשובים כדי שיוכל אחרי זה לעזור לכם לחפש מידע בתיקיית המייל.

להתקנה נפעיל:

sudo apt-get install mailutils

הפעלה ראשונית היא פשוט:

mu index

ואחר כך אפשר להפעיל פקודות כמו:

mu find git

כדי למצוא את כל הודעות הדואר שלכם בהן הופיעה המילה git. ל mu יש גם מנגנון חיפוש באנשי קשר ולכן הפקודה:

mu cfind ynon

תציג לי את כל כתובות המייל שהתכתבתי איתן שמכילות את הטקסט ynon. יש שם גם שפת תכנות מובנית שנקראת guile אבל בינתיים לא הצלחתי להשתמש בה. מה שכן עובד זה חיבור ל Python עם המודול mailbox. התוכנית הבאה למשל עוברת על תיבת הדואר הנכנס שלי ומראה כמה אימיילים קיבלתי מכל חבר:

import mailbox
from collections import Counter

friends = Counter()
for message in mailbox.Maildir('~/Maildir/INBOX'):
    friends.update([message['From']])

print(friends)

החיבור לפייתון מספק בסיס טוב לאוטומציות למי שאוהב את זה.

3. סינכרון אוטומטי

כדי לעדכן את תיבת המייל אנחנו מפעילים את mbsync ואחריו את mu index. כמובן שאין טעם להריץ את זה ידנית אז כתבתי Shell Script בשם refresh_emails.sh:

#!/usr/bin/bash

{
  /usr/bin/mbsync fastmail

  pkill -2 -u -x $UID mu
  /usr/bin/mu index

} >& /dev/null

ואני מריץ אותו דרך קרון כל 5 דקות:

*/5 * * * * ~/bin/refresh_emails.sh

יש גם פיתרונות יותר מתוחכמים שמשתמשים במנגנון Push של imap כדי להפעיל את הסינכרון רק כשבאמת יש דואר חדש, אבל אני בינתיים לא מצאתי משהו שהצלחתי לעבוד איתו.

4. קריאת דואר עם mutt

עם כל הכבוד לאוטומציות אין תחליף לתוכנה פשוטה שמציגה דואר ומאחר ואנחנו כבר רגילים לעבוד בתוך המסוף אין יותר טוב מתוכנת מסוף שקוראת וכותבת דואר. התוכנה נקראת mutt והיא לוקחת את הגדרות הצבעים והפונטים מהטרמינל, אבל החלק הכי טוב זה שאפשר לקבוע לעצמכם את קיצורי המקשים וגם לבנות macro-ים.

התקנה על ubuntu נראית כך:

$ sudo apt-get install mutt

וזאת הקונפיגורציה שלי מינוס סיסמאות ומידע רגיש כפי שמוגדרת בקובץ ~/.muttrc:

# Folder with emails
set folder = "~/Maildir/"
# Type of mailbox
set mbox_type = Maildir
# Directory to poll for new mail
set spoolfile = +INBOX
# Directory to save sent messages into
set record = +Sent
# Sets the drafts folder
set postponed = +Drafts
# File that headers will be cached
set header_cache = ~/.cache/mutt

set realname = "Ynon Perek"
set from     = "YOUR-EMAIL-ADDRESS-HERE"

# smtp url format: "smtp://email_address:password@smtp-server.com:587/"
set smtp_url  = "YOUR-SMTP-URL-HERE"
set ssl_force_tls = yes
set ssl_starttls = yes

set query_command = "mu cfind --format=mutt-ab '%s'"

bind editor <Tab> complete-query
bind editor ^T complete

# Sort by threads
set sort = threads
# Sort threads by last date recieved - newest first
set sort_aux = reverse-last-date-received
# Show date in year/month/day hour:minute format
set date_format="%d/%m/%y %H:%M"
set index_format="%4C %Z %d %-15.15L (%?l?%4l&%4c?) %s"

# Keybindings and macros {{{1
# ---------------------------

# alias   - alias menu displaying suggested aliases
# browser - file/directory browser
# editor  - single line editor for `To:', `Subject:' prompts.
# index   - the main menu showing messages in a folder
# pager   - where the contents of the message are displayed
# query   - menu displaying results of query command

bind index g noop
bind pager g noop

# Unbind some defaults.
bind index <esc>V noop
bind index <esc>v noop
bind index \Cn noop
bind index \Cp noop


# macro index,pager A ":set confirmappend=no delete=yes <save-message>=Archive<enter>" "Archive Message"
macro index a ":set confirmappend=no delete=yes auto_tag=yes\n\
    <save-message>=Archive\n:set delete=ask-yes\n" "Archive Message"

macro pager a "<save-message>=Archive\n" "Archive Message"

bind alias,index,browser,query G last-entry
bind pager G bottom

bind alias,index,browser,query gg first-entry
bind pager gg top

bind alias,index,pager,browser,query \Cd half-down
bind alias,index,pager,browser,query \Cu half-up

bind index <esc><space> collapse-all
bind index <space> collapse-thread

bind index n search-next
bind index p search-opposite

bind index { previous-thread
bind pager { half-up

bind index } next-thread
bind pager } half-down

bind index,pager ,n sidebar-toggle-visible
# Move the highlight to the previous mailbox
bind index,pager \Cp sidebar-prev
# Move the highlight to the next mailbox
bind index,pager \Cn sidebar-next
# Open the highlighted mailbox
bind index,pager \Co sidebar-open


# Skip trash when deleting with the delete key.
bind index,pager <delete> purge-message

# Readline-like history browsing using up/down keys.
bind editor <up> history-up
bind editor <down> history-down


# Go to folder...
macro index,pager gi "<change-folder>=INBOX<enter>"       "open inbox"
macro index,pager gd "<change-folder>=Drafts<enter>"      "open drafts"
macro index,pager gs "<change-folder>=Sent<enter>"        "open sent"
macro index,pager gt "<change-folder>$trash<enter>"       "open trash"
macro index,pager gf "<change-folder>?"                   "open mailbox..."
macro index,pager ga "<change-folder>=Archive<enter><buffy-list>"   "open archive"

# I use this whenever I know that a folder hook is acting and I just want the
# message to go to the default save folder.
macro index,pager I "<save-message><enter>" "save message to default folder without confirming"


# Limit messages quickly using ' + key.
macro index \'d  "<limit>~D<enter>"       "limit to deleted messages"
macro index \'f  "<limit>~F<enter>"       "limit to flagged messages"
macro index \'l  "<limit>~=<enter>"       "limit to duplicate messages"
macro index \'n  "<limit>~N|~O<enter>"    "limit to new messages"
macro index \'p  "<limit>~g|~G<enter>"    "limit to signed or encrypted messages"
macro index \'u  "<limit>!~Q<enter>"      "limit to unreplied messages"
macro index \'\' "<limit>~A<enter>"       "reset all limits"

# If +spam doesn't exist, mutt will create it for us.
macro index S "<save-message>+spam<enter>" "mark message as spam"


# Toggle the mailbox list with "y".
macro index,pager y "<change-folder>?<toggle-mailboxes>" "show incoming mailboxes list"
bind browser y exit

# Call urlview with Ctrl + B.
macro index,pager,attach,compose \cb                                            \
  "<enter-command>set my_pipe_decode=\$pipe_decode pipe_decode<Enter>           \
  <pipe-message>urlview<Enter>                                                  \
  <enter-command>set pipe_decode=\$my_pipe_decode; unset my_pipe_decode<Enter>" \
  "call urlview to extract URLs out of a message"


# Pipe message to pbcopy with Ctrl + Y.  pipe_decode will ensure that
# unnecessary headers are removed and the message is processed.
macro index,pager,attach,compose \cy                                            \
  "<enter-command>set my_pipe_decode=\$pipe_decode pipe_decode<Enter>           \
  <pipe-message>pbcopy<Enter>                                                   \
  <enter-command>set pipe_decode=\$my_pipe_decode; unset my_pipe_decode<Enter>" \
  "copy message to clipboard using mutt-pbcopy"

macro index ,/ \
  "<enter-command>set my_old_pipe_decode=\$pipe_decode my_old_wait_key=\$wait_key nopipe_decode nowait_key<enter>\
  <shell-escape>notmuch-mutt -r --prompt search<enter>\
  <change-folder-readonly>`echo ${XDG_CACHE_HOME:-$HOME/.cache}/notmuch/mutt/results`<enter>\
  <enter-command>set pipe_decode=\$my_old_pipe_decode wait_key=\$my_old_wait_key<enter>" \
        "notmuch: search mail"

בכניסה ראשונה ל mutt כדאי ללחוץ על סימן שאלה (הכפתור במקלדת ?) ואז מקבלים רשימה של כל קיצורי המקשים שהגדרנו בקונפיגורציה ואלה המובנים של mutt.

בגלל שכל המייל נשמר מקומית אתם יכולים להפעיל את mutt כדי לקרוא מיילים ולחפש בתיבה גם בלי חיבור לאינטרנט, ויש לכם גיבוי של כל המיילים שלכם אם אי פעם גוגל יחליטו לנעול אתכם מחוץ לחשבון. בזכות יכולות ההרחבה של mutt אתם יכולים לבנות כל ממשק שמתאים לכם ולא מחויבים לממשק של גוגל.

באופן אוטומטי mutt לוקח את עורך הטקסט ממשתנה הסביבה EDITOR. אני משתמש באימקס בשביל התמיכה בעברית ולכן מפעיל את mutt באופן הבא:

EDITOR=emacs mutt

(ברירת המחדל שלי ל EDITOR היא כמובן vim).

5. מה עוד נשאר

אני מאוד אוהב את הסטאפ הזה והרבה יותר קל לי לענות למיילים מאשר בעבר. גם קריאת מיילים עובדת מהר יותר כי כולם שמורים אצלי מקומית.

בעיה אחת שעדיין נשארה היא האהבה של רוב העולם ל HTML Emails במיוחד בכתיבת עברית. מתוך mutt המיילים שאני שולח הם מבוססי טקסט ולכן אין אפשרות לכתוב בפונטים גדולים, צבעים או הדגשות. כאן יש דיון מעניין עם רעיון לחבר את pandoc כדי לכתוב את האימייל במארקדאון ואז להפוך אותו ל HTML (לא ניסיתי):

https://unix.stackexchange.com/questions/108485/send-email-written-in-markdown-using-mutt

את ההשראה לפוסט ורעיונות נוספים לקונפיגורציה קיבלתי מ copyninja ואם גם אתם מחפשים עוד רעיונות לסטאפים שווה לקרוא את הפוסט כאן:

My personal Email setup - Notmuch, mbsync, postfix and dovecot