Sende eine in Markdown geschriebene E-Mail mit mutt

21

Manchmal muss ich ein Codefragment in Google Group Inline senden. Text hilft hier nicht; Ich kann es in Markdown eingeben, in HTML konvertieren (mit Pandoc usw.), an Mutt als anhängen text/htmlund es senden.

Es gibt eine gute Lösung zur Verfügung hier aber es nutzt externes sendmailProgramm E - Mail senden. Ich benutze Mutt, der die Fähigkeit hat, E-Mails über IMAP selbst zu senden .

Dilawar
quelle
1
Warum nicht einfach die Ausgabe von einem Kommandozeilen-Markdown-Formatierer umleiten sendmail?
Naftuli Kay
Hmm .. gemeinsamer Computer! Ich möchte kein Passwort für externes sendmail speichern.
Dilawar
Gibt es Beispiele dafür, wie Ihre aktuellen Ergebnisse in Google Groups aussehen?
slm
Sie möchten auch Dinge in Markdown eingeben, aber haben sie gerendert, bevor Sie sie an Ihre E-Mails anhängen, oder?
SLM
Dies klingt wie das, wonach Sie fragen, muss aber möglicherweise geändert werden: dgl.cx/2009/03/html-mail-with-mutt-using-markdown . Auch markdownmail.py klang nach etwas, das man benutzen könnte.
SLM

Antworten:

28

Nachdem Sie eine Nachricht verfasst haben, stehen Ihnen jedoch vor dem Senden zahlreiche Optionen zur Verfügung. Drücken Sie ?, um sie anzuzeigen.

Einige, die hier helfen können:

  • F um den Anhang durch einen externen Prozessor zu filtern
    • Verwenden Sie pandoc -s -f markdown -t htmlzu konvertieren , um HTML
  • ^T um den Anhangs-MIME-Typ zu bearbeiten
    • Ändern Sie von text/plainzu text/html.

Jetzt ein Makro, das alles in einem Schritt erledigt. Fügen Sie dies zu Ihrem hinzu .muttrc:

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

Um dieses Makro zu verwenden, drücken Sie nach dem Verfassen der Nachricht, aber vor dem Senden, Escdann 5, um die abschriftenformatierte Nachricht in HTML zu konvertieren.

Sie können dieses Makro natürlich nach Belieben anpassen. In Mutt sind bereits viele Tastenzuordnungen integriert. Stellen Sie also sicher, dass keine andere Tastenzuordnung überschrieben wird (oder dass Sie darauf verzichten können).


Die Option set wait_key=nounterdrückt die Press any key to continue...Eingabeaufforderung von Mutt, wenn externe Befehle ausgeführt werden. Wenn wait_keyist yes(dies ist die Standardeinstellung), müssen Sie eine beliebige andere Taste drücken Esc, 5um fortzufahren.

Bahamat
quelle
1
Dies ist eine wirklich elegante Lösung! +1
sinisterstuf
5
Das ist schön, aber es hat Kernfehler. es beseitigt den Klartext-Teil der E-Mail, der es nervt, Clients wie ... mutt einzulesen;) HTML-E-Mails sollten eine Klartext- und eine HTML-Komponente haben. Der rohe Markdown sollte der Klartext sein, der konvertierte sollte der HTML-Code sein.
Masukomi
1
Wenn Sie mit @masukomi einverstanden sind, senden E-Mail-Clients im Allgemeinen sowohl HTML- als auch Textversionen der E-Mail. Es wäre schön, ein Makro zu haben, das die HTML-Version hinzufügt und das Original als Text / Plain belässt.
pepper_chico
2
Am Ende habe ich mein eigenes Setup für diese nosubstance.me/post/mutt-secret-sauce
pepper_chico
1

Sendmail ist oft nicht flexibel genug, um Mails zu versenden.

Ich benutze Msmtp zusammen mit Mutt auf bestimmten Konten für flexibles SMTP.

Um es mit mutt change zu benutzen:

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

und

# ~/.msmtprc  
defaults
tls off
logfile ~/.msmtp.log  
account default   
host your.smtp.host  
port 25  
from [email protected]  
auth off  
user username  
password password  

quelle
0

Ich habe es geschafft. Ich bin nicht ganz glücklich über meine Lösung, aber sie ist anständig genug. Warten auf eine andere Person, um eine bessere Lösung zu finden.

Der Prozess folgt. Konvertieren Sie den Markdown in HTML und hängen Sie ihn an die Nachricht an. Drehen Sie diesen Anhang zu inlineAnhang. Aber jetzt habe ich zwei Anhänge, der erste ist in Markdown und der zweite ist HTML. Ersetzen Sie den Markdown-Inhalt durch eine leere Zeichenfolge, damit nur HTML gesendet wird.

Ich habe der ~/.muttrcDatei die folgende Zeile hinzugefügt .

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

Hier ist, email-editorwas von dem Link in Frage gestellt entlehnt ist.

#!/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

Und die Haupt-Python-Datei, die aufgerufen wird, folgt. Dies ist inspiriert vom Perl-Skript des betreffenden Links.

#!/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)

Dies hängt von einer weiteren Python-Datei ab, formatter.pydie pandoczum Formatieren meiner E-Mails verwendet wird. Wenn sie pandocnicht verfügbar ist, kann sie python-markdown2package verwenden. Dieses Skript folgt.

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

Diese Dateien sind auch hier verfügbar: https://github.com/dilawar/mutt

Dilawar
quelle
0

Ich kann E-Mails in jedem Format senden neomutt. Ich benutze nur Emacs(org-mode), anstatt vim. Obwohl ich auch ein vimBenutzer bin . Aber ich benutze meistens Emacsmit bösen Modus.

In meinem habe .muttrcich emacsstattdessen den Editor eingerichtet vim. Beim Schreiben einer neuen E-Mail wird neomuttausgelöst emacs. Dann rufe ich "org-mode" auf, schreibe die Nachricht und exportiere sie in das von mir gewünschte Format.

Ich kann in das PDFFormat exportieren . Dann speichere ich es und hänge die PDFDatei in meine /tmp. Danach kann ich an wen auch immer senden.

Wenn ich das htmlFormat möchte , exportiere ich es auf die gleiche Weise und kann die Ausgabe automatisch sehen, bevor ich die E-Mail versende.

Abgesehen davon gibt es viele andere Exportformate im org-Modus. Wählen Sie einfach, was Sie wollen. Wenn Sie Code an andere Personen senden möchten, fügen Sie den Quellcode einfach der gewünschten Sprache hinzu. Alles wird im org-wiki erklärt .

Achylles
quelle
0

Sie können E-Mails auch multipart/alternativemit text/plainund versenden text/html.

Anforderungen: Pandoc

Grundsätzlich erstellt es aus Markdown-Nachricht Klartext und HTML5. Erstellt aus diesen Teilen Anhänge, markiert sie als Inline-Anhänge, legt den richtigen MIME-Typ fest und kombiniert sie zu einer mehrteiligen Nachricht.

Alle anderen Anhänge sollten hinzugefügt werden, nachdem dieses Makro im Menü "Erstellen" ausgeführt wurde. Optionales Signieren / Verschlüsseln der Nachricht sollte als letzter Schritt erfolgen

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" 
Jakub Jindra
quelle