Populate dotfiles repository
This commit is contained in:
29
neomutt/.config/neomutt/accounts/gmail.muttrc
Normal file
29
neomutt/.config/neomutt/accounts/gmail.muttrc
Normal file
@@ -0,0 +1,29 @@
|
||||
# vim: filetype=neomuttrc
|
||||
# muttrc file for account gmail
|
||||
set realname = "Amin Kasrou Aouam"
|
||||
set from = "akasroua@gmail.com"
|
||||
set sendmail = "./.config/neomutt/etc/sendmail gmail"
|
||||
set folder = "~/.mail/gmail"
|
||||
#set header_cache = ~/.config/mutt/accounts/gmail/cache/headers
|
||||
#set message_cachedir = ~/.config/mutt/accounts/gmail/cache/bodies
|
||||
#set certificate_file = ~/.config/mutt/accounts/gmail/certificates
|
||||
#source "~/.config/mutt/credentials/getmuttpass gmail |"
|
||||
|
||||
set mbox_type = Maildir
|
||||
set ssl_starttls = yes
|
||||
set ssl_force_tls = yes
|
||||
|
||||
set record = "+sent"
|
||||
bind index,pager gg noop
|
||||
bind index,pager g noop
|
||||
bind index gg first-entry
|
||||
unmailboxes *
|
||||
mailboxes =gmail =------------------- =junk =Inbox =trash =sent
|
||||
macro index,pager gi "<change-folder>=Inbox<enter>" "Go to inbox."
|
||||
macro index,pager gs "<change-folder>=sent<enter>" "Go to sent."
|
||||
macro index,pager gt "<change-folder>=trash<enter>" "Go to trash."
|
||||
macro index,pager gj "<change-folder>=junk<enter>" "Go to spam."
|
||||
set spoolfile = "+Inbox"
|
||||
set record = "+sent"
|
||||
set postponed = ""
|
||||
set trash = "+trash"
|
||||
28
neomutt/.config/neomutt/accounts/uni.muttrc
Normal file
28
neomutt/.config/neomutt/accounts/uni.muttrc
Normal file
@@ -0,0 +1,28 @@
|
||||
# vim: filetype=neomuttrc
|
||||
# muttrc file for account coolneng
|
||||
set realname = "Amin Kasrou Aouam"
|
||||
set from = "akasroua@correo.ugr.es"
|
||||
set sendmail = "./.config/neomutt/etc/sendmail uni"
|
||||
set folder = "~/.mail/uni"
|
||||
#set header_cache = ~/.config/mutt/accounts/coolneng/cache/headers
|
||||
#set message_cachedir = ~/.config/mutt/accounts/coolneng/cache/bodies
|
||||
#set certificate_file = ~/.config/mutt/accounts/coolneng/certificates
|
||||
#source "~/.config/mutt/credentials/getmuttpass coolneng |"
|
||||
|
||||
set mbox_type = Maildir
|
||||
set ssl_starttls = yes
|
||||
set ssl_force_tls = yes
|
||||
|
||||
bind index,pager gg noop
|
||||
bind index,pager g noop
|
||||
bind index gg first-entry
|
||||
unmailboxes *
|
||||
mailboxes =uni =------------------- =INBOX =trash =sent =archive
|
||||
macro index,pager gi "<change-folder>=INBOX<enter>" "Go to inbox."
|
||||
macro index,pager gs "<change-folder>=sent<enter>" "Go to sent."
|
||||
macro index,pager gt "<change-folder>=trash<enter>" "Go to trash."
|
||||
macro index,pager ga "<change-folder>=archive<enter>" "Go to archive."
|
||||
set spoolfile = "+INBOX"
|
||||
set record = "+sent"
|
||||
set postponed = ""
|
||||
set trash = "+trash"
|
||||
22
neomutt/.config/neomutt/etc/aliases
Normal file
22
neomutt/.config/neomutt/etc/aliases
Normal file
@@ -0,0 +1,22 @@
|
||||
## A file for aliases
|
||||
|
||||
# Uni staff
|
||||
alias dani dmolina@decsai.ugr.es
|
||||
alias cano carloscano@ugr.es
|
||||
alias paco carranzafr@ugr.es
|
||||
alias mesa cdemesa@decsai.ugr.es
|
||||
|
||||
# Uni students
|
||||
alias elenche elenche@correo.ugr.es
|
||||
alias bezout jesusmartinz@correo.ugr.es
|
||||
alias lesca lesca98@correo.ugr.es
|
||||
alias oumnia oumnia487@correo.ugr.es
|
||||
alias juanca jclm@correo.ugr.es
|
||||
|
||||
# Personal
|
||||
alias barbas arodasaparicio@gmail.com
|
||||
alias rafika rafibel63@gmail.com
|
||||
alias oekk luismata06@gmail.com
|
||||
alias walid mkasrou@gmail.com
|
||||
alias walida naouam61@gmail.com
|
||||
alias tarek tarek@tarcript.me
|
||||
131
neomutt/.config/neomutt/etc/gpg.rc
Normal file
131
neomutt/.config/neomutt/etc/gpg.rc
Normal file
@@ -0,0 +1,131 @@
|
||||
# -*-muttrc-*-
|
||||
#
|
||||
# Command formats for gpg.
|
||||
#
|
||||
# Version notes:
|
||||
#
|
||||
# GPG 2.1 introduces the option "--pinentry-mode", which requires
|
||||
# the "loopback" argument in instances where "--passphrase-fd" is
|
||||
# used.
|
||||
#
|
||||
# Some of the older commented-out versions of the commands use gpg-2comp from:
|
||||
# http://70t.de/download/gpg-2comp.tar.gz
|
||||
#
|
||||
# %p The empty string when no passphrase is needed,
|
||||
# the string "PGPPASSFD=0" if one is needed.
|
||||
#
|
||||
# This is mostly used in conditional % sequences.
|
||||
#
|
||||
# %f Most PGP commands operate on a single file or a file
|
||||
# containing a message. %f expands to this file's name.
|
||||
#
|
||||
# %s When verifying signatures, there is another temporary file
|
||||
# containing the detached signature. %s expands to this
|
||||
# file's name.
|
||||
#
|
||||
# %a In "signing" contexts, this expands to the value of the
|
||||
# configuration variable $pgp_sign_as, if set, otherwise
|
||||
# $pgp_default_key. You probably need to
|
||||
# use this within a conditional % sequence.
|
||||
#
|
||||
# %r In many contexts, neomutt passes key IDs to pgp. %r expands to
|
||||
# a list of key IDs.
|
||||
|
||||
# Section A: Key Management
|
||||
|
||||
# The default key for encryption (used by $pgp_self_encrypt and
|
||||
# $postpone_encrypt).
|
||||
#
|
||||
# It will also be used for signing unless $pgp_sign_as is set to a
|
||||
# key.
|
||||
#
|
||||
# Unless your key does not have encryption capability, uncomment this
|
||||
# line and replace the keyid with your own.
|
||||
#
|
||||
# set pgp_default_key="0x12345678"
|
||||
|
||||
# If you have a separate signing key, or your key _only_ has signing
|
||||
# capability, uncomment this line and replace the keyid with your
|
||||
# signing keyid.
|
||||
#
|
||||
# set pgp_sign_as="0x87654321"
|
||||
|
||||
|
||||
# Section B: Commands
|
||||
|
||||
# Note that we explicitly set the comment armor header since GnuPG, when used
|
||||
# in some localiaztion environments, generates 8bit data in that header, thereby
|
||||
# breaking PGP/MIME.
|
||||
|
||||
# decode application/pgp
|
||||
#
|
||||
set pgp_decode_command="gpg --status-fd=2 %?p?--pinentry-mode loopback --passphrase-fd 0? --no-verbose --quiet --batch --output - %f"
|
||||
|
||||
# Verify a signature
|
||||
#
|
||||
set pgp_verify_command="gpg --status-fd=2 --no-verbose --quiet --batch --output - --verify %s %f"
|
||||
|
||||
# Decrypt an attachment
|
||||
#
|
||||
set pgp_decrypt_command="gpg --status-fd=2 %?p?--pinentry-mode loopback --passphrase-fd 0? --no-verbose --quiet --batch --output - --decrypt %f"
|
||||
|
||||
# Create a PGP/MIME signed attachment
|
||||
#
|
||||
# set pgp_sign_command="gpg-2comp --comment '' --no-verbose --batch --output - %?p?--passphrase-fd 0? --armor --detach-sign --textmode %?a?-u %a? %f"
|
||||
#
|
||||
set pgp_sign_command="gpg %?p?--pinentry-mode loopback --passphrase-fd 0? --no-verbose --batch --quiet --output - --armor --textmode %?a?--local-user %a? --detach-sign %f"
|
||||
|
||||
# Create a application/pgp inline signed message. This style is obsolete but still needed for Hushmail recipients and some MUAs.
|
||||
#
|
||||
# set pgp_clearsign_command="gpg-2comp --comment '' --no-verbose --batch --output - %?p?--passphrase-fd 0? --armor --textmode --clearsign %?a?-u %a? %f"
|
||||
#
|
||||
set pgp_clearsign_command="gpg %?p?--pinentry-mode loopback --passphrase-fd 0? --no-verbose --batch --quiet --output - --armor --textmode %?a?--local-user %a? --clearsign %f"
|
||||
|
||||
# Create an encrypted attachment (note that some users include the --always-trust option here)
|
||||
#
|
||||
# set pgp_encrypt_only_command="/usr/libexec/neomutt/pgpewrap gpg-2comp -v --batch --output - --encrypt --textmode --armor --always-trust -- -r %r -- %f"
|
||||
#
|
||||
set pgp_encrypt_only_command="/usr/libexec/neomutt/pgpewrap gpg --batch --quiet --no-verbose --output - --textmode --armor --encrypt -- --recipient %r -- %f"
|
||||
|
||||
# Create an encrypted and signed attachment (note that some users include the --always-trust option here)
|
||||
#
|
||||
# set pgp_encrypt_sign_command="/usr/libexec/neomutt/pgpewrap gpg-2comp %?p?--passphrase-fd 0? -v --batch --output - --encrypt --sign %?a?-u %a? --armor --always-trust -- -r %r -- %f"
|
||||
#
|
||||
set pgp_encrypt_sign_command="/usr/libexec/neomutt/pgpewrap gpg %?p?--pinentry-mode loopback --passphrase-fd 0? --batch --quiet --no-verbose --textmode --output - %?a?--local-user %a? --armor --sign --encrypt -- --recipient %r -- %f"
|
||||
|
||||
# Import a key into the public key ring
|
||||
#
|
||||
set pgp_import_command="gpg --no-verbose --import %f"
|
||||
|
||||
# Export a key from the public key ring
|
||||
#
|
||||
set pgp_export_command="gpg --no-verbose --armor --export %r"
|
||||
|
||||
# Verify a key
|
||||
#
|
||||
set pgp_verify_key_command="gpg --verbose --batch --fingerprint --check-sigs %r"
|
||||
|
||||
# Read in the public key ring
|
||||
#
|
||||
set pgp_list_pubring_command="gpg --no-verbose --batch --quiet --with-colons --with-fingerprint --with-fingerprint --list-keys %r"
|
||||
|
||||
# Read in the secret key ring
|
||||
#
|
||||
set pgp_list_secring_command="gpg --no-verbose --batch --quiet --with-colons --with-fingerprint --with-fingerprint --list-secret-keys %r"
|
||||
|
||||
# Fetch keys
|
||||
# set pgp_getkeys_command="pkspxycwrap %r"
|
||||
|
||||
# pattern for good signature - may need to be adapted to locale!
|
||||
# OK, here's a version which uses gnupg's message catalog:
|
||||
# set pgp_good_sign="^gpgv?: Good signature from"
|
||||
# set pgp_good_sign="`gettext -d gnupg -s 'Good signature from "' | tr -d '"'`"
|
||||
#
|
||||
# Output pattern to indicate a valid signature using --status-fd messages
|
||||
set pgp_good_sign="^\\[GNUPG:\\] GOODSIG"
|
||||
|
||||
# Output pattern to verify a decryption occurred
|
||||
# This is now deprecated by pgp_check_gpg_decrypt_status_fd:
|
||||
# set pgp_decryption_okay="^\\[GNUPG:\\] DECRYPTION_OKAY"
|
||||
set pgp_check_gpg_decrypt_status_fd
|
||||
|
||||
6
neomutt/.config/neomutt/etc/mailcap
Normal file
6
neomutt/.config/neomutt/etc/mailcap
Normal file
@@ -0,0 +1,6 @@
|
||||
text/html; w3m -I %{charset} -T text/html %s; copiousoutput;
|
||||
text/* ; vim %s ; edit=vim %s ; compose=vim %s ; needsterminal
|
||||
image/*; sxiv %s ; copiousoutput
|
||||
application/pdf; zathura %s ;
|
||||
application/docx; libreoffice %s ;
|
||||
application/pgp-encrypted; gpg -d '%s'; copiousoutput;
|
||||
71
neomutt/.config/neomutt/etc/muttcol
Normal file
71
neomutt/.config/neomutt/etc/muttcol
Normal file
@@ -0,0 +1,71 @@
|
||||
# vim: filetype=neomuttrc
|
||||
|
||||
# Default index colors:
|
||||
color index yellow default '.*'
|
||||
color index_author red default '.*'
|
||||
color index_number blue default
|
||||
color index_subject cyan default '.*'
|
||||
|
||||
# For new mail:
|
||||
color index brightyellow black "~N"
|
||||
color index_author brightred black "~N"
|
||||
color index_subject brightcyan black "~N"
|
||||
|
||||
# Header colors:
|
||||
color header blue default ".*"
|
||||
color header brightmagenta default "^(From)"
|
||||
color header brightcyan default "^(Subject)"
|
||||
color header brightwhite default "^(CC|BCC)"
|
||||
|
||||
mono bold bold
|
||||
mono underline underline
|
||||
mono indicator reverse
|
||||
mono error bold
|
||||
color normal default default
|
||||
color indicator brightblack white
|
||||
color sidebar_highlight red default
|
||||
color sidebar_divider brightblack black
|
||||
color sidebar_flagged red black
|
||||
color sidebar_new green black
|
||||
color normal brightyellow default
|
||||
color error red default
|
||||
color tilde black default
|
||||
color message cyan default
|
||||
color markers red white
|
||||
color attachment white default
|
||||
color search brightmagenta default
|
||||
color status brightyellow black
|
||||
color hdrdefault brightgreen default
|
||||
color quoted green default
|
||||
color quoted1 blue default
|
||||
color quoted2 cyan default
|
||||
color quoted3 yellow default
|
||||
color quoted4 red default
|
||||
color quoted5 brightred default
|
||||
color signature brightgreen default
|
||||
color bold black default
|
||||
color underline black default
|
||||
color normal default default
|
||||
|
||||
color body brightred default "[\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+" # Email addresses
|
||||
color body brightblue default "(https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+" # URL
|
||||
color body green default "\`[^\`]*\`" # Green text between ` and `
|
||||
color body brightblue default "^# \.*" # Headings as bold blue
|
||||
color body brightcyan default "^## \.*" # Subheadings as bold cyan
|
||||
color body brightgreen default "^### \.*" # Subsubheadings as bold green
|
||||
color body yellow default "^(\t| )*(-|\\*) \.*" # List items as yellow
|
||||
color body brightcyan default "[;:][-o][)/(|]" # emoticons
|
||||
color body brightcyan default "[;:][)(|]" # emoticons
|
||||
color body brightcyan default "[*]?((N)?ACK|CU|LOL|SCNR|BRB|BTW|CWYL|\
|
||||
|FWIW|vbg|GD&R|HTH|HTHBE|IMHO|IMNSHO|\
|
||||
|IRL|RTFM|ROTFL|ROFL|YMMV)[*]?"
|
||||
color body brightcyan default "[ ][*][^*]*[*][ ]?" # more emoticon?
|
||||
color body brightcyan default "[ ]?[*][^*]*[*][ ]" # more emoticon?
|
||||
color body red default "(BAD signature)"
|
||||
color body cyan default "(Good signature)"
|
||||
color body brightblack default "^gpg: Good signature .*"
|
||||
color body brightyellow default "^gpg: "
|
||||
color body brightyellow red "^gpg: BAD signature from.*"
|
||||
mono body bold "^gpg: Good signature"
|
||||
mono body bold "^gpg: BAD signature from.*"
|
||||
color body red default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]""']))']))']))']))']))']))']))']))']))']))']))']))'])']))))))])]"
|
||||
3
neomutt/.config/neomutt/etc/sendmail
Executable file
3
neomutt/.config/neomutt/etc/sendmail
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
./.local/bin/MIMEmbellish | msmtp -a $1 -t
|
||||
1
neomutt/.config/neomutt/keys/gmail.gpg
Normal file
1
neomutt/.config/neomutt/keys/gmail.gpg
Normal file
@@ -0,0 +1 @@
|
||||
<EFBFBD>
|
||||
1
neomutt/.config/neomutt/keys/uni.gpg
Normal file
1
neomutt/.config/neomutt/keys/uni.gpg
Normal file
@@ -0,0 +1 @@
|
||||
<EFBFBD>
|
||||
89
neomutt/.config/neomutt/neomuttrc
Normal file
89
neomutt/.config/neomutt/neomuttrc
Normal file
@@ -0,0 +1,89 @@
|
||||
#vim: filetype=neomuttrc
|
||||
# This is the general mutt config which has the settings that all accounts use.
|
||||
bind index,pager i noop
|
||||
bind index,pager g noop
|
||||
bind index \Cf noop
|
||||
source etc/muttcol
|
||||
source etc/aliases
|
||||
source personal.muttrc
|
||||
set sleep_time = 0
|
||||
set sort = 'reverse-date'
|
||||
set editor = $EDITOR
|
||||
set copy = no
|
||||
set timeout = "15"
|
||||
set mail_check = "30"
|
||||
set imap_idle = yes
|
||||
set beep_new = yes
|
||||
set mailcap_path = ~/.config/neomutt/etc/mailcap
|
||||
set date_format="%d/%m/%y %H:%M"
|
||||
set index_format="%2C %zs %?X?A& ? %D %-15.15F %s (%-4.4c)"
|
||||
set markers = no
|
||||
set mark_old = no
|
||||
set mime_forward = yes
|
||||
set smtp_authenticators = 'gssapi:login'
|
||||
set wait_key = no
|
||||
auto_view text/html
|
||||
auto_view application/pgp-encrypted
|
||||
alternative_order text/plain text/enriched text/html
|
||||
set rfc2047_parameters = yes
|
||||
set send_charset = 'us-ascii:utf-8'
|
||||
set ssl_use_tlsv1_2=yes
|
||||
|
||||
# General remappings
|
||||
bind editor <space> noop
|
||||
bind index G last-entry
|
||||
bind index gg first-entry
|
||||
bind pager j next-line
|
||||
bind pager k previous-line
|
||||
bind pager gg top
|
||||
bind pager G bottom
|
||||
bind index d half-down
|
||||
bind index u half-up
|
||||
bind index D delete-message
|
||||
bind index U undelete-message
|
||||
bind index F search
|
||||
bind index,pager R group-reply
|
||||
bind index,pager \031 previous-undeleted # Mouse wheel
|
||||
bind index,pager \005 next-undeleted # Mouse wheel
|
||||
macro index,pager S <sync-mailbox>
|
||||
macro index,pager \Cu |urlscan\n
|
||||
macro index,pager ,, |urlscan\n
|
||||
|
||||
# View attachments properly.
|
||||
bind attach <return> view-mailcap
|
||||
set fast_reply # skip to compose when replying
|
||||
set fcc_attach # save attachments with the body
|
||||
unset mime_forward # forward attachments as part of body
|
||||
set forward_format = "Fwd: %s" # format of subject when forwarding
|
||||
set forward_decode # decode when forwarding
|
||||
set forward_quote # include message in forwards
|
||||
set reverse_name # reply as whomever it was to
|
||||
set include # include message in replies
|
||||
|
||||
#Ctrl-R to mark all as read
|
||||
macro index \Cr "T~U<enter><tag-prefix><clear-flag>N<untag-pattern>.<enter>" "mark all messages as read"
|
||||
#
|
||||
# #sync email
|
||||
macro index o "<shell-escape>mbsync -a 2>/dev/null 1>&2 &<enter>" "run mbsync to sync all mail"
|
||||
|
||||
# #copy/move dialogs
|
||||
macro index C "<copy-message>?<toggle-mailboxes>" "copy a message to a mailbox"
|
||||
macro index M "<save-message>?<toggle-mailboxes>" "move a message to a mailbox"
|
||||
|
||||
# Notmuch searching
|
||||
macro index \Cf "<enter-command>unset wait_key<enter><shell-escape>read -p 'notmuch query: ' x; echo \$x >~/.cache/mutt_terms<enter><limit>~i \"\`notmuch search --output=messages \$(cat ~/.cache/mutt_terms) | head -n 600 | perl -le '@a=<>;chomp@a;s/\^id:// for@a;$,=\"|\";print@a'\`\"<enter>" "show only messages matching a notmuch pattern"
|
||||
macro index A "<limit>all\n" "show all messages (undo limit)"
|
||||
|
||||
# # Sidebar mappings
|
||||
set sidebar_visible = yes
|
||||
set sidebar_width = 20
|
||||
set sidebar_short_path = yes
|
||||
set sidebar_next_new_wrap = yes
|
||||
set mail_check_stats
|
||||
set sidebar_format = '%B%?F? [%F]?%* %?N?%N/? %?S?%S?'
|
||||
bind index,pager \Ck sidebar-prev
|
||||
bind index,pager \Cj sidebar-next
|
||||
bind index,pager \Co sidebar-open
|
||||
bind index,pager \Cp sidebar-prev-new
|
||||
bind index,pager \Cn sidebar-next-new
|
||||
bind index,pager B sidebar-toggle-visible
|
||||
4
neomutt/.config/neomutt/personal.muttrc
Normal file
4
neomutt/.config/neomutt/personal.muttrc
Normal file
@@ -0,0 +1,4 @@
|
||||
macro index,pager i1 '<sync-mailbox><enter-command>source "/home/coolneng/.config/neomutt"/accounts/gmail.muttrc<enter><change-folder>!<enter>'
|
||||
source /home/coolneng/.config/neomutt/accounts/gmail.muttrc
|
||||
macro index,pager i2 '<sync-mailbox><enter-command>source "/home/coolneng/.config/neomutt"/accounts/uni.muttrc<enter><change-folder>!<enter>'
|
||||
source /home/coolneng/.config/neomutt/accounts/uni.muttrc
|
||||
238
neomutt/.local/bin/MIMEmbellish/MIMEmbellish
Executable file
238
neomutt/.local/bin/MIMEmbellish/MIMEmbellish
Executable file
@@ -0,0 +1,238 @@
|
||||
#!/usr/local/bin/python3.6
|
||||
|
||||
import re
|
||||
import sys
|
||||
import email
|
||||
import shlex
|
||||
import mimetypes
|
||||
import subprocess
|
||||
from copy import copy
|
||||
from hashlib import md5
|
||||
from email import charset
|
||||
from email import encoders
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.nonmultipart import MIMENonMultipart
|
||||
from os.path import basename, splitext, expanduser
|
||||
|
||||
|
||||
charset.add_charset('utf-8', charset.SHORTEST, '8bit')
|
||||
|
||||
|
||||
def pandoc(from_format, to_format='markdown', plain='markdown', title=None):
|
||||
markdown = ('markdown'
|
||||
'-blank_before_blockquote')
|
||||
|
||||
if from_format == 'plain':
|
||||
from_format = plain
|
||||
if from_format == 'markdown':
|
||||
from_format = markdown
|
||||
if to_format == 'markdown':
|
||||
to_format = markdown
|
||||
|
||||
command = 'pandoc -f {} -t {} --standalone --highlight-style=tango'
|
||||
if to_format in ('html', 'html5'):
|
||||
if title is not None:
|
||||
command += ' --variable=pagetitle:{}'.format(shlex.quote(title))
|
||||
command += ' --webtex --template={}'.format(
|
||||
expanduser('~/.pandoc/templates/email.html'))
|
||||
return command.format(from_format, to_format)
|
||||
|
||||
|
||||
def gmailfy(payload):
|
||||
return payload.replace('<blockquote>',
|
||||
'<blockquote class="gmail_quote" style="'
|
||||
'padding: 0 7px 0 7px;'
|
||||
'border-left: 2px solid #cccccc;'
|
||||
'font-style: italic;'
|
||||
'margin: 0 0 7px 3px;'
|
||||
'">')
|
||||
|
||||
|
||||
def make_alternative(message, part):
|
||||
alternative = convert(part, 'html',
|
||||
pandoc(part.get_content_subtype(),
|
||||
to_format='html',
|
||||
title=message.get('Subject')))
|
||||
alternative.set_payload(gmailfy(alternative.get_payload()))
|
||||
return alternative
|
||||
|
||||
|
||||
def make_replacement(message, part):
|
||||
return convert(part, 'plain', pandoc(part.get_content_subtype()))
|
||||
|
||||
|
||||
def convert(part, to_subtype, command):
|
||||
payload = part.get_payload()
|
||||
if isinstance(payload, str):
|
||||
payload = payload.encode('utf-8')
|
||||
else:
|
||||
payload = part.get_payload(None, True)
|
||||
if not isinstance(payload, bytes):
|
||||
payload = payload.encode('utf-8')
|
||||
process = subprocess.run(
|
||||
shlex.split(command),
|
||||
input=payload, stdout=subprocess.PIPE, check=True)
|
||||
return MIMEText(process.stdout, to_subtype, 'utf-8')
|
||||
|
||||
|
||||
def with_alternative(parent, part, from_signed,
|
||||
make_alternative=make_alternative,
|
||||
make_replacement=None):
|
||||
try:
|
||||
alternative = make_alternative(parent or part, from_signed or part)
|
||||
replacement = (make_replacement(parent or part, part)
|
||||
if from_signed is None and make_replacement is not None
|
||||
else part)
|
||||
except:
|
||||
return parent or part
|
||||
envelope = MIMEMultipart('alternative')
|
||||
if parent is None:
|
||||
for k, v in part.items():
|
||||
if (k.lower() != 'mime-version'
|
||||
and not k.lower().startswith('content-')):
|
||||
envelope.add_header(k, v)
|
||||
del part[k]
|
||||
envelope.attach(replacement)
|
||||
envelope.attach(alternative)
|
||||
if parent is None:
|
||||
return envelope
|
||||
payload = parent.get_payload()
|
||||
payload[payload.index(part)] = envelope
|
||||
return parent
|
||||
|
||||
|
||||
def tag_attachments(message):
|
||||
if message.get_content_type() == 'multipart/mixed':
|
||||
for part in message.get_payload():
|
||||
if (part.get_content_maintype() in ['image']
|
||||
and 'Content-ID' not in part):
|
||||
filename = part.get_param('filename',
|
||||
header='Content-Disposition')
|
||||
if isinstance(filename, tuple):
|
||||
filename = str(filename[2], filename[0] or 'us-ascii')
|
||||
if filename:
|
||||
filename = splitext(basename(filename))[0]
|
||||
if filename:
|
||||
part.add_header('Content-ID', '<{}>'.format(filename))
|
||||
return message
|
||||
|
||||
|
||||
def attachment_from_file_path(attachment_path):
|
||||
try:
|
||||
mime, encoding = mimetypes.guess_type(attachment_path, strict=False)
|
||||
maintype, subtype = mime.split('/')
|
||||
with open(attachment_path, 'rb') as payload:
|
||||
attachment = MIMENonMultipart(maintype, subtype)
|
||||
attachment.set_payload(payload.read())
|
||||
encoders.encode_base64(attachment)
|
||||
if encoding:
|
||||
attachment.add_header('Content-Encoding', encoding)
|
||||
return attachment
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
attachment_path_pattern = re.compile(r'\]\s*\(\s*file://(/[^)]*\S)\s*\)|'
|
||||
r'\]\s*:\s*file://(/.*\S)\s*$',
|
||||
re.MULTILINE)
|
||||
|
||||
|
||||
def link_attachments(payload):
|
||||
attached = []
|
||||
attachments = []
|
||||
|
||||
def on_match(match):
|
||||
if match.group(1):
|
||||
attachment_path = match.group(1)
|
||||
cid_fmt = '](cid:{})'
|
||||
else:
|
||||
attachment_path = match.group(2)
|
||||
cid_fmt = ']: cid:{}'
|
||||
attachment_id = md5(attachment_path.encode()).hexdigest()
|
||||
if attachment_id in attached:
|
||||
return cid_fmt.format(attachment_id)
|
||||
attachment = attachment_from_file_path(attachment_path)
|
||||
if attachment:
|
||||
attachment.add_header('Content-ID', '<{}>'.format(attachment_id))
|
||||
attachments.append(attachment)
|
||||
attached.append(attachment_id)
|
||||
return cid_fmt.format(attachment_id)
|
||||
return match.group()
|
||||
|
||||
return attachments, attachment_path_pattern.sub(on_match, payload)
|
||||
|
||||
|
||||
def with_local_attachments(parent, part, from_signed,
|
||||
link_attachments=link_attachments):
|
||||
if from_signed is None:
|
||||
attachments, payload = link_attachments(part.get_payload())
|
||||
part.set_payload(payload)
|
||||
else:
|
||||
attachments, payload = link_attachments(from_signed.get_payload())
|
||||
from_signed = copy(from_signed)
|
||||
from_signed.set_payload(payload)
|
||||
if not attachments:
|
||||
return parent, part, from_signed
|
||||
if parent is None:
|
||||
parent = MIMEMultipart('mixed')
|
||||
for k, v in part.items():
|
||||
if (k.lower() != 'mime-version'
|
||||
and not k.lower().startswith('content-')):
|
||||
parent.add_header(k, v)
|
||||
del part[k]
|
||||
parent.attach(part)
|
||||
for attachment in attachments:
|
||||
parent.attach(attachment)
|
||||
return parent, part, from_signed
|
||||
|
||||
|
||||
def is_target(part, target_subtypes):
|
||||
return (part.get('Content-Disposition', 'inline') == 'inline'
|
||||
and part.get_content_maintype() == 'text'
|
||||
and part.get_content_subtype() in target_subtypes)
|
||||
|
||||
|
||||
def pick_from_signed(part, target_subtypes):
|
||||
for from_signed in part.get_payload():
|
||||
if is_target(from_signed, target_subtypes):
|
||||
return from_signed
|
||||
|
||||
|
||||
def seek_target(message, target_subtypes=['plain', 'markdown']):
|
||||
if message.is_multipart():
|
||||
if message.get_content_type() == 'multipart/signed':
|
||||
part = pick_from_signed(message, target_subtypes)
|
||||
if part is not None:
|
||||
return None, message, part
|
||||
elif message.get_content_type() == 'multipart/mixed':
|
||||
for part in message.get_payload():
|
||||
if part.is_multipart():
|
||||
if part.get_content_type() == 'multipart/signed':
|
||||
from_signed = pick_from_signed(part, target_subtypes)
|
||||
if from_signed is not None:
|
||||
return message, part, from_signed
|
||||
elif is_target(part, target_subtypes):
|
||||
return message, part, None
|
||||
else:
|
||||
if is_target(message, target_subtypes):
|
||||
return None, message, None
|
||||
return None, None, None
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
message = email.message_from_file(sys.stdin)
|
||||
parent, part, from_signed = seek_target(message)
|
||||
if (parent, part, from_signed) == (None, None, None):
|
||||
print(message)
|
||||
return
|
||||
tag_attachments(message)
|
||||
print(with_alternative(
|
||||
*with_local_attachments(parent, part, from_signed)))
|
||||
except (BrokenPipeError, KeyboardInterrupt):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user