R сбой с segfault при вызове функции с сеткой - PullRequest
0 голосов
/ 23 мая 2019

Я пытаюсь написать пакет R с функцией отправки электронных писем с помощью модуля smtplib в python. Функция работает, когда я получаю ее напрямую или с помощью devtools::load_all(), но выдает ошибку R, когда я библиотеку своего пакета и вызываю функцию.

Я использовал пакет mailR, который использует Java для отправки электронной почты, но у меня возникли проблемы после обновления версии Java. Я решил написать быстрый пакет, чтобы заменить его версией Python. Все работало, как и ожидалось, пока я не установил его с devtools::install_local(), а затем попытался вызвать функцию. У меня нет большого опыта работы с python, я чувствую, что это может быть связано с тем, как я импортирую модули python, я пытался переместить импорт внутри функции, но это не помогло.

Это функция python, которую я использую с сеткой:

import smtplib  
import re
from os.path import basename
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.utils import COMMASPACE, formatdate


def py_sendmail(send_from, send_to, subject, 
                text_body = None, html_body = None, 
                inline = False, authenticate = False, ssl = False,
                smtp_server = None, port = 587, username = None,
                password = None, send = True, attach_files = None,
                debug = False):

  img_content = []

  msg = MIMEMultipart('related')
  msg['From'] = send_from
  msg['To'] = send_to
  msg['Date'] = formatdate(localtime=True)
  msg['Subject'] = subject

  if inline == True:

    img_re = re.compile("<img(?:.+?)src\s*=\s*(?P<quote>['\"])(?P<imgurl>.*?)(?P=quote)")
    imgs = img_re.findall(html_body)
    img_cnt = 1

    for(q, imgurl) in imgs:
      fp = open(imgurl, 'rb')
      msg_img = MIMEImage(fp.read())
      fp.close()
      img_id = "image" + str(img_cnt) 
      msg_img.add_header("Content-ID", "<"+img_id+">")
      img_content.append(msg_img)
      html_body = re.sub(imgurl, "cid:"+img_id, html_body)
      img_cnt = img_cnt + 1

  if text_body is not None and html_body is not None:
    msgAlt = MIMEMultipart('alternative')
    msg.attach(msgAlt)
    msgAlt.attach(MIMEText(text_body, 'plain'))
    msgAlt.attach(MIMEText(html_body, 'html'))

  elif text_body is not None:
    msg.attach(MIMEText(text_body, 'plain'))

  elif html_body is not None:
    msg.attach(MIMEText(html_body, 'html'))

  if attach_files is not None:

    for f in attach_files or []:
      with open(f, 'rb') as fil:
        part = MIMEApplication(
          fil.read(),
          Name=basename(f)
        )
        part['Content-Disposition'] = 'attachment; filename="%s"' % basename(f)
        msg.attach(part)

  if len(img_content) > 0:
    for img in img_content:
      msg.attach(img)

  if send == True:

    if ssl == True:
      server = smtplib.SMTP_SSL(smtp_server, port)
    else:
      server = smtplib.SMTP(smtp_server, port)

    if authenticate == True:
      server.login(username, password)

    x = server.sendmail(send_from, send_to, msg.as_string())
    server.quit()
    return x == {}

  else:
    return msg.as_string()

Он должен отправлять электронное письмо, и это происходит при получении в глобальной среде или при загрузке с devtools::load_all(). Но если я установлю его с devtools::install_local() и запишу его в библиотеку, он вылетает R. Когда я запускаю его в RStudio, он вылетает без объяснения причин, когда я запускаю его из командной строки, я получаю следующее:

> library(pymailr)
> pymailr:::py_sendmail("<from_address>", "<to_address>", "Test",
+             text_body = "Testing", html_body = "<h1>Testing</h1>",
+             inline = FALSE, authenticate = TRUE, ssl = TRUE,
+             smtp_server = "<smtp_server>", port = 465, username = "<user_name>",
+             password = "<password>", send = TRUE)

 *** caught segfault ***
address (nil), cause 'memory not mapped'

Traceback:
 1: py_call_impl(callable, dots$args, dots$keywords)
 2: pymailr:::py_sendmail("<from_address>", "<to_address>", "Test",     text_body = "Testing", html_body = "<h1>Testing</h1>", inline = FALSE,     authenticate = TRUE, ssl = TRUE, smtp_server = "<smtp_server>",     port = 465, username = "<username>", password = "<password>",     send = TRUE)
...