Enviar correo electrónico escrito en markdown usando mutt


21

A veces necesito enviar un fragmento de código en google-group en línea. El texto no ayuda aquí; Puedo escribirlo en markdown, convertirlo a html (usando pandoc, etc.), adjuntarlo a mutt as text/htmly enviarlo.

Aquí hay una buena solución disponible , pero utiliza un sendmailprograma externo para enviar correos electrónicos. Estoy usando mutt que tiene la capacidad de enviar correos electrónicos a través de IMAP por sí mismo.


1
¿Por qué no simplemente canalizar la salida de un formateador Markdown de línea de comandos a sendmail?
Naftuli Kay

Hmm .. computadora compartida! No quiero almacenar la contraseña para sendmail externo.
Dilawar

¿Hay algún ejemplo que podamos ver de cómo se ven sus resultados actuales en google-groups?
slm

También desea escribir las cosas en markdown, pero hacer que se procesen antes de adjuntarlas a sus correos electrónicos, ¿verdad?
slm

Esto suena como lo que está pidiendo, pero es posible que deba modificarse: dgl.cx/2009/03/html-mail-with-mutt-using-markdown . También markdownmail.py sonaba como algo que podrías usar.
slm

Respuestas:


28

Después de redactar un mensaje, pero antes de enviarlo, tiene muchas opciones disponibles. Presione ?para verlos.

Algunos que pueden ayudar aquí:

  • F para filtrar el archivo adjunto a través de un procesador externo
    • Use pandoc -s -f markdown -t htmlpara convertir a HTML
  • ^T para editar el tipo MIME adjunto
    • Cambiar de text/plaina text/html.

Ahora una macro que hará todo en un solo paso. Agregue esto a su .muttrc:

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

Para usar esta macro, una vez que haya terminado de redactar su mensaje pero antes de enviarlo, presione y Escluego 5convierta su mensaje con formato de descuento a HTML.

Naturalmente, puede personalizar esta macro como mejor le parezca. Mutt tiene muchas asociaciones de teclas ya integradas, por lo que sea cual sea la secuencia de teclas que elija vincular, asegúrese de que no sobrescriba otra cosa (o es algo sin lo que puede vivir).


La opción set wait_key=nosuprime el Press any key to continue...mensaje de Mutt cuando se ejecutan comandos externos. Si wait_keyes yes(que es el valor predeterminado), tendrá que presionar Esc, luego 5, cualquier otra tecla para continuar.


1
¡Esta es una solución realmente elegante! +1
sinisterstuf

55
Esto es bueno, pero tiene un defecto central. elimina la parte de texto sin formato del correo electrónico, lo que hace que sea difícil leer en clientes como ... mutt;) Los correos electrónicos HTML deben tener un componente de texto sin formato y html. la rebaja sin formato debe ser el texto sin formato, el convertido debe ser el HTML.
masukomi

1
De acuerdo con @masukomi, los clientes de correo electrónico en general envían versiones html y de texto del correo electrónico. Sería bueno tener una macro que agregue la versión html y deje el original como texto / sin formato.
pepper_chico

2
Al final, he creado mi propia configuración para este nosubstance.me/post/mutt-secret-sauce
pepper_chico


1

Sendmail a menudo no es lo suficientemente flexible como para enviar correos.

Utilizo msmtp junto con mutt en cuentas particulares para SMTP flexible.

Para usarlo con mutt change:

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

y

# ~/.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

Pude hacerlo. No estoy del todo contento con mi solución, pero es lo suficientemente decente. Esperando que alguien más brinde una mejor solución.

El proceso está siguiendo. Convierta el markdown a html y adjúntelo al mensaje. Convierta este archivo adjunto en inlinearchivo adjunto. Pero ahora tengo dos archivos adjuntos, el primero está en markdown y el segundo es html. Reemplace el contenido de rebajas con una cadena vacía para que solo se envíe html.

Agregué la siguiente línea al ~/.muttrcarchivo.

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

Aquí está lo email-editorque está prestado del enlace publicado en cuestión.

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

Y el archivo principal de Python que se llama está siguiendo. Esto está inspirado en el script perl del enlace en cuestión.

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

Esto depende de un archivo python más llamado formatter.pyque se usa pandocpara formatear mi correo, pero si pandocno está disponible, puede usar el python-markdown2paquete. Este script está siguiendo.

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

Estos archivos también están disponibles aquí https://github.com/dilawar/mutt


0

Puedo enviar correos electrónicos en cualquier formato usando neomutt. Solo uso Emacs(org-mode), en lugar de vim. Aunque, yo también soy un vimusuario. Pero, principalmente lo uso Emacscon el modo malvado.

En mi .muttrche configurado el editor para que sea en emacslugar de vim. Al escribir un nuevo correo electrónico, se neomuttenciende emacs. Luego llamo "org-mode", escribo el mensaje y exporto al formato que quiera.

Puedo exportar a PDFformato. Luego lo guardo y adjunto el PDFarchivo en mi /tmp. Después de eso puedo enviar a quien sea.

Si quiero el htmlformato, lo exporto de la misma manera y automáticamente puedo ver la salida, antes de enviar el correo electrónico.

Aparte de eso, hay muchos otros formatos de exportación en modo org. Solo elige lo que quieras. Para enviar código a otras personas, simplemente agregue el código fuente al idioma que desee. Todo se explica en el org-wiki .


0

Puede enviar correos electrónicos también como que multipart/alternativecontienen ambos text/plainy text/html.

Requisitos: pandoc

Básicamente se crea a partir de mensajes de texto sin formato y html5. Crea archivos adjuntos a partir de esas partes, los marca como archivos adjuntos en línea, establece el tipo mime correcto y los combina en un mensaje mutlipart.

Se supone que se agregarán otros archivos adjuntos después de ejecutar esta macro en el menú de redacción. Opcionalmente, se debe firmar / cifrar el mensaje como paso final

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" 
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.