Invia e-mail scritta in markdown usando mutt


21

A volte devo inviare un frammento di codice in linea al gruppo di Google. Il testo non aiuta qui; Posso scriverlo in markdown, convertirlo in html (usando pandoc ecc.), Collegarlo a mutt as text/htmle inviarlo.

C'è una buona soluzione disponibile qui ma utilizza un sendmailprogramma esterno per inviare e-mail. Sto usando Mutt che ha le capacità di inviare e-mail su IMAP da solo.


1
Perché non eseguire semplicemente il piping dell'output da un formattatore Markdown della riga di comando a sendmail?
Naftuli Kay,

Mmm .. computer condiviso! Non voglio archiviare la password per sendmail esterno.
Dilawar,

Ci sono esempi che possiamo vedere su come appaiono i tuoi risultati attuali sui gruppi di Google?
slm

Inoltre vuoi scrivere le cose in markdown, ma le hai renderizzate prima di allegarle alle tue e-mail, giusto?
slm

Questo suona come quello che stai chiedendo, ma potrebbe essere necessario modificarlo: dgl.cx/2009/03/html-mail-with-mutt-using-markdown . Anche markdownmail.py sembrava qualcosa che potevi usare.
slm

Risposte:


28

Dopo aver composto un messaggio, ma prima di inviarlo sono disponibili molte opzioni. Premere ?per visualizzarli.

Alcuni che possono aiutare qui:

  • F per filtrare l'allegato attraverso un processore esterno
    • Utilizzare pandoc -s -f markdown -t htmlper convertire in HTML
  • ^T per modificare il tipo MIME dell'allegato
    • Cambia da text/plaina text/html.

Ora una macro che farà tutto in un solo passaggio. Aggiungi questo al tuo .muttrc:

macro compose \e5 "F pandoc -s -f markdown -t html \ny^T^Utext/html; charset=us-ascii\n"
set wait_key=no

Per utilizzare questa macro, dopo aver finito di comporre il messaggio ma prima di inviarlo, premere Escquindi 5per convertire il messaggio formattato per il markdown in HTML.

Puoi personalizzare questa macro come preferisci. Mutt ha già un sacco di combinazioni di tasti incorporate, quindi qualunque sequenza di tasti tu scelga di associare, assicurati che non sovrascriva qualcos'altro (o è qualcosa senza cui puoi vivere).


L'opzione set wait_key=noelimina il Press any key to continue...prompt di Mutt quando vengono eseguiti comandi esterni. Se wait_keyè yes(che è l'impostazione predefinita) dovrai premere Esc, quindi 5, qualsiasi altro tasto per continuare.


1
Questa è una soluzione davvero elegante! +1
sinisterstuf,

5
è bello, ma ha un difetto centrale. elimina la parte in chiaro dell'email che la fa leggere in client come ... mutt;) Le e-mail HTML dovrebbero avere un componente in testo semplice e HTML. il markdown grezzo dovrebbe essere il testo normale, il convertito dovrebbe essere l'HTML.
Masukomi,

1
D'accordo con @masukomi, i client di posta elettronica in generale inviano sia la versione html che quella testuale dell'email. Sarebbe bello avere una macro che aggiunge la versione html e lascia l'originale come testo / chiaro.
pepper_chico,

2
Alla fine ho creato il mio setup per questo nosubstance.me/post/mutt-secret-sauce
pepper_chico


1

Sendmail spesso non è un enogh flessibile per l'invio di mail.

Uso msmtp insieme a mutt su account particolari per SMTP flessibile.

Per usarlo con mutt change:

# ~/.muttrc  
set sendmail="/usr/bin/msmtp -a default"   

e

# ~/.msmtprc  
defaults
tls off
logfile ~/.msmtp.log  
account default   
host your.smtp.host  
port 25  
from your-user-name@your-host.com  
auth off  
user username  
password password  

0

Sono stato in grado di farlo. Non sono del tutto contento della mia soluzione, ma è abbastanza decente. In attesa che qualcun altro fornisca una soluzione migliore.

Il processo sta seguendo. Converti il ​​markdown in html e allegalo al messaggio. Trasforma questo allegato in inlineallegato. Ma ora ho due allegati, il primo è in markdown e il secondo è html. Sostituisci il contenuto del markdown con una stringa vuota in modo che venga inviato solo html.

Ho aggiunto la seguente riga al ~/.muttrcfile.

macro compose B ":set editor=text2mime-markdown.py<enter>E:set editor=email-editor<enter>Da/tmp/html-markdown-alternative.html<enter>^Du"

Ecco email-editorquale è preso in prestito dal link pubblicato in questione.

#!/bin/sh
if grep -q In-Reply-To $1; then
  # Jump to first line of message
  exec vim -c 'norm }j' $1
else
  # Enter insert mode on the To: line
  exec vim  $1
fi

E il seguente file Python che viene chiamato è il seguente. Questo si ispira allo script perl dal link in questione.

#!/usr/bin/env python
import os
import sys
from formatter import *
version = "0.1"

file = sys.argv[1]
new_file = "/tmp/html-markdown-alternative.html"
with open(file, "r") as f:
    text = f.read()

lines = text.split('\n')
header = []
body = []
headerStart = True
for l in lines:
    if headerStart:
        m = re.search(r'^[\w\-]+\:', l)
        if m:
            header.append(l)
        else:
            headerStart = False
            body.append(l)
    else:
        body.append(l)

header = '\n'.join(header)
body = '\n'.join(body)

htmlBody = markdownToHtml(body);

html = []
html.append('<html>')
html.append('<head>')
html.append('<meta name=\"generator\" content=\"text2mime-markdown{}\">'.format(version))
html.append('<style>')
html.append("code { font-family: 'Andale Mono', 'Lucida Console', \
        'Bitstream Vera Sans Mono', 'Courier New', monospace; }")
html.append('pre { border-left: 20px solid #ddd; margin-left: 10px; \
        padding-left: 5px; }')
html.append('</style>')
html.append('</head>')
html.append('<body>')
html.append('{0}'.format(body))
html.append('</body>')
html.append('</html>')
html = '\n'.join(html)

with open(new_file, "w") as newF:
    newF.write(html)

with open(file, 'w') as f:
    f.write(header)

Questo dipende da un altro file Python chiamato formatter.pyche utilizza pandocper formattare la mia posta ma se pandocnon è disponibile può usare il python-markdown2pacchetto. Questo script sta seguendo.

import subprocess
import re
import os 
import sys
import html2text 
import collections

# check if pandoc exists
panDoc = True
try:
    subprocess.call(["pandoc", '--version']
            , stdout=subprocess.PIPE
            , stdin=subprocess.PIPE
            )
except OSError:
    panDoc = False

if not panDoc:
    import text.html2text as html2text
    import markdown 

def decodeText(text):
    return text.decode('utf-8')

def markdownToHtml(content, convertor='pandoc'):
    global panDoc
    if panDoc:
        cmd = ["pandoc", "-f", "markdown", "-t", "html"]
        p = subprocess.Popen(cmd
                , stdin = subprocess.PIPE
                , stdout = subprocess.PIPE
                )
        p.stdin.write(content)
        content = p.communicate()[0]
        return decodeText(content)
    else:
        return markdown.markdown(decodeText(content))


def htmlToMarkdown(content, convertor='pandoc'):
    global panDoc
    if panDoc and convertor == 'pandoc':
        cmd = ["pandoc", "-t", "markdown", "-f", "html"]
        p = subprocess.Popen(cmd
                , stdin = subprocess.PIPE
                , stdout = subprocess.PIPE
                )
        p.stdin.write(content)
        content = p.communicate()[0]
        return decodeText(content)
    # Use markdown package to convert markdown to html
    else:
        h = html2text.HTML2Text()
        content = h.handle(decodeText(content))
        return content

def titleToBlogDir(title):
    if title is None:
        return ''
    if len(title.strip()) == 0:
        return ''
    blogDir = title.replace(" ","_").replace(':', '-').replace('(', '')
    blogDir = blogDir.replace('/', '').replace('\\', '').replace('`', '')
    blogDir = blogDir.replace(')', '').replace("'", '').replace('"', '')
    return blogDir

def titleToFilePath(title, blogDir):
    if len(blogDir.strip()) == 0:
        return ''
    fileName = os.path.join(blogDir, titleToBlogDir(title))
    return fileName


def htmlToHtml(html):
    return decodeText(html)

def metadataDict(txt):
    mdict = collections.defaultdict(list)
    md = getMetadata(txt)
    for c in ["title", 'type', "layout", "status", "id", "published", "category", "tag"]:
        pat = re.compile(r'{0}\:\s*(?P<name>.+)'.format(c), re.IGNORECASE)
        m = pat.findall(txt)
        for i in m:
            mdict[c].append(i)
    return mdict

def getMetadata(txt):
   """
   Get metadata out of a txt
   """
   if not "---" in txt:
       print txt
       sys.exit(1)

   pat = re.compile(r'\-\-\-+(?P<metadata>.+?)\-\-\-+', re.DOTALL)
   m = pat.search(txt)
   if m:
       return m.group('metadata')
   else:
       sys.exit(0)

def getContent(txt):
    """ 
    Return only text of the post.
    """
    pat = re.compile(r'\-\-\-+(?P<metadata>.+?)\-\-\-+', re.DOTALL)
    return re.sub(pat, "", txt)

def readInputFile(fileName):
    """
    read file and return its format. html or markdown
    """
    assert fileName
    if not os.path.exists(fileName):
        raise IOError, "File %s does not exists" % fileName

    # Check the fmt of file.
    fmt = os.path.splitext(fileName)[1].lower()
    if fmt in ["htm", "html", "xhtml"]:
        fmt = "html"
    elif fmt in ["md", "markdown"]:
        fmt = "markdown"
    else:
        fmt = "markdown"
    txt = open(fileName, 'r').read()   
    return (fmt, txt)

def formatContent(txt, fmt):
    """
    Format the content as per fmt.
    """
    content = getContent(txt)
    if fmt == "html":
        content = htmlToHtml(content)
    elif fmt == "markdown":
        content = markdownToHtml(content)
    else:
        content = markdownToHtml(content)
    return content

Questi file sono disponibili anche qui https://github.com/dilawar/mutt


0

Posso inviare e-mail in qualsiasi formato utilizzando neomutt. Io uso solo Emacs(modalità org), invece di vim. Anche se sono un vimutente. Ma lo uso principalmente Emacscon la modalità malvagia.

Nel mio .muttrcho impostato l'editor per essere emacsinvece di vim. Quando si scrive una nuova e-mail, si neomuttaccende emacs. Quindi chiamo "org-mode", scrivo il messaggio ed esporto nel formato che desidero.

Posso esportare in PDFformato. Quindi lo salvo e allego il PDFfile nel mio /tmp. Dopodiché posso inviare a chiunque.

Se voglio il htmlformato, lo esporto allo stesso modo e vedo automaticamente l'output, prima di inviare l'e-mail.

A parte questo, ci sono molti altri formati di esportazione in modalità org. Scegli semplicemente quello che vuoi. Per inviare il codice ad altre persone, aggiungi semplicemente il codice sorgente nella lingua che desideri. Tutto è spiegato nell'org-wiki .


0

È possibile inviare e-mail anche come multipart/alternativecontenenti entrambi text/plaine text/html.

Requisiti: pandoc

Fondamentalmente crea dal messaggio markdown in chiaro e html5. Crea allegati da quelle parti, li contrassegna come allegati incorporati, imposta il tipo MIME corretto e li combina in un messaggio a più parti.

Ogni altro allegato dovrebbe essere aggiunto dopo aver eseguito questa macro nel menu di composizione. Opzionalmente la firma / crittografia del messaggio dovrebbe essere eseguita come passaggio finale

macro compose ,m \
"<enter-command>set pipe_decode<enter>\
<pipe-message>pandoc -f gfm -t plain -o /tmp/msg.txt<enter>\
<pipe-message>pandoc -s -f gfm -t html5 -o /tmp/msg.html<enter>\
<enter-command>unset pipe_decode<enter>a^U/tmp/msg.txt\n^Da^U/tmp/msg.html\n^D^T^Utext/html; charset=utf-8\n=DTT&d^U\n" \
"Convert markdown gfm to HTML and plain" 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.