Gửi email bằng văn bản markdown bằng mutt


21

Đôi khi tôi cần gửi một đoạn mã trên dòng nội tuyến google. Văn bản không giúp đỡ ở đây; Tôi có thể gõ nó trong markdown, chuyển đổi nó thành html (sử dụng pandoc, v.v.), đính kèm vào mutt như text/htmlvà gửi nó.

Có một giải pháp tốt có sẵn ở đây nhưng nó sử dụng sendmailchương trình bên ngoài để gửi email. Tôi đang sử dụng mutt có khả năng gửi email qua IMAP .


1
Tại sao không chỉ đầu ra đường ống từ một định dạng Markdown dòng lệnh đến sendmail?
Naftuli Kay

Hmm .. máy tính dùng chung! Không muốn lưu trữ mật khẩu cho sendmail bên ngoài.
Dilawar

Có bất kỳ ví dụ nào chúng ta có thể thấy kết quả hiện tại của bạn trông như thế nào trên các nhóm google không?
slm

Ngoài ra, bạn muốn nhập mọi thứ trong markdown, nhưng chúng đã được hiển thị trước khi đính kèm chúng vào email của bạn, phải không?
slm

Điều này nghe có vẻ như những gì bạn đang yêu cầu, nhưng có thể cần phải sửa đổi: dgl.cx/2009/03/html-mail-with-mutt-USE-markdown . Ngoài ra markdownmail.py nghe có vẻ như một cái gì đó bạn có thể sử dụng.
slm

Câu trả lời:


28

Sau khi bạn soạn một tin nhắn, nhưng trước khi gửi, bạn có rất nhiều tùy chọn có sẵn cho bạn. Nhấn ?để xem chúng.

Một số có thể giúp ở đây:

  • F để lọc tệp đính kèm thông qua bộ xử lý bên ngoài
    • Sử dụng pandoc -s -f markdown -t htmlđể chuyển đổi sang HTML
  • ^T để chỉnh sửa loại MIME đính kèm
    • Thay đổi từ text/plainsang text/html.

Bây giờ một macro sẽ làm mọi thứ trong một bước. Thêm phần này vào .muttrc:

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

Để sử dụng macro này, sau khi bạn đã hoàn thành việc soạn thư của bạn nhưng trước khi bạn gửi, báo chí Escsau đó 5để chuyển đổi định dạng thông điệp markdown của bạn vào HTML.

Bạn có thể tự nhiên tùy chỉnh macro này khi bạn thấy phù hợp. Mutt có rất nhiều ràng buộc khóa đã được tích hợp sẵn, do đó, bất kỳ chuỗi khóa nào bạn chọn để liên kết, hãy đảm bảo rằng nó không ghi đè lên một thứ khác (hoặc đó là thứ bạn có thể sống mà không có).


Tùy chọn set wait_key=nongăn chặn Press any key to continue...dấu nhắc của Mutt khi các lệnh bên ngoài được chạy. Nếu wait_keyyes(mặc định) bạn sẽ phải nhấn Esc, sau đó 5, bất kỳ phím nào khác để tiếp tục.


1
Đây là một giải pháp thực sự thanh lịch! +1
sinisterstuf

5
Điều này là tốt, nhưng nó có lỗ hổng cốt lõi. nó loại bỏ phần văn bản gốc của email khiến nó bị đọc khi đọc trong các máy khách như ... mutt;) Các email HTML phải có thành phần văn bản và html. đánh dấu thô phải là bản rõ, bản chuyển đổi phải là HTML.
masukomi

1
Đồng ý với @masukomi, các ứng dụng email nói chung gửi cả phiên bản html và văn bản của email. Sẽ thật tuyệt nếu có một macro thêm phiên bản html và để nguyên bản dưới dạng văn bản / thuần túy.
pepper_chico

2
Cuối cùng, tôi đã xây dựng thiết lập của riêng mình cho nosubstance.me/post/mutt-secret-sauce
pepper_chico


1

Sendmail thường không linh hoạt enogh để gửi thư.

Tôi sử dụng msmtp cùng với mutt trên các tài khoản cụ thể cho SMTP linh hoạt.

Để sử dụng nó với thay đổi mutt:

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

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

Tôi đã có thể làm điều đó. Tôi không hoàn toàn hài lòng về giải pháp của mình nhưng nó đủ tốt. Chờ đợi người khác cung cấp một giải pháp tốt hơn.

Quá trình là sau. Chuyển đổi markdown thành html và đính kèm nó vào tin nhắn. Biến tập tin đính kèm này thành inlinetập tin đính kèm. Nhưng bây giờ tôi có hai tệp đính kèm, đầu tiên là markdown và thứ hai là html. Thay thế nội dung đánh dấu bằng chuỗi trống để chỉ gửi html.

Tôi đã thêm dòng sau vào ~/.muttrctập tin.

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

Đây là email-editorcái được mượn từ liên kết được đăng trong câu hỏi.

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

Và tập tin python chính được gọi là sau đây. Điều này được lấy cảm hứng từ kịch bản perl từ liên kết trong câu hỏi.

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

Điều này phụ thuộc vào một tệp python được gọi là formatter.pysử dụng pandocđể định dạng thư của tôi nhưng nếu pandockhông có sẵn, nó có thể sử dụng python-markdown2gói. Kịch bản này là sau.

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

Các tệp này cũng có sẵn tại đây https://github.com/dilawar/mutt


0

Tôi có thể gửi email ở bất kỳ định dạng nào bằng cách sử dụng neomutt. Tôi chỉ sử dụng Emacs(chế độ org), thay vì vim. Mặc dù, tôi là một vimngười dùng là tốt. Nhưng, tôi chủ yếu sử dụng Emacsvới chế độ ác.

Trong tôi .muttrctôi đã thiết lập trình soạn thảo để emacsthay thế vim. Khi viết một email mới, neomuttkích hoạt emacs. Sau đó, tôi gọi "chế độ org", viết tin nhắn và xuất thành bất kỳ định dạng nào tôi muốn.

Tôi có thể xuất sang PDFđịnh dạng. Sau đó, tôi lưu nó và đính kèm các PDFtập tin trong của tôi /tmp. Sau đó tôi có thể gửi cho bất cứ ai.

Nếu tôi muốn htmlđịnh dạng, tôi xuất nó theo cùng một cách và tôi tự động có thể thấy đầu ra, trước khi gửi email.

Ngoài ra, có nhiều định dạng xuất khác trong chế độ org. Chỉ cần chọn những gì bạn muốn. Để gửi mã cho người khác, chỉ cần thêm mã nguồn vào bất kỳ ngôn ngữ nào bạn muốn. Tất cả mọi thứ được giải thích trong org-wiki .


0

Bạn cũng có thể gửi e-mail dưới dạng multipart/alternativechứa cả hai text/plaintext/html.

Yêu cầu: pandoc

Về cơ bản, nó tạo ra từ bản rõ thông điệp markdown và html5. Tạo tệp đính kèm từ các phần đó, đánh dấu chúng là tệp đính kèm nội tuyến, đặt loại mime chính xác và kết hợp chúng thành thông điệp mutlipart.

Bất kỳ tệp đính kèm nào khác được cho là sẽ được thêm vào sau khi chạy macro này trong menu soạn thảo. Tùy chọn ký / mã hóa tin nhắn nên được thực hiện như bước cuối cùng

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" 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.