首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从gjs gtk应用程序发送电子邮件(衍生邮件)

如何从gjs gtk应用程序发送电子邮件(衍生邮件)
EN

Stack Overflow用户
提问于 2019-01-26 03:18:39
回答 1查看 241关注 0票数 1

我正在尝试写一个gjs应用程序,需要发送电子邮件。我发现的方法是使用spawn_async_with_pipes()调用邮件。这个应用程序似乎产生了邮件,我没有收到错误,但我没有得到任何有用的输出,也没有收到测试电子邮件……

我在这方面已经有一段时间了,几乎没有找到有用的最新文档。我正在使用gtk3和gjs (以及glib)。我还尝试生成一个shell脚本,该脚本依次调用mail。这导致了“无法解析主机”错误和死信队列。所以我知道我正在生成我的命令。我关心的不是“无法解析主机命令”,而是我不能通过直接生成邮件来获得它的事实。

我是这样产生邮件的:

代码语言:javascript
运行
复制
const [res, pid, in_fd, out_fd, err_fd] =
await GLib.spawn_async_with_pipes(null,
                                              ['mail',
                                              '-V',
                                              `-s "${msgObj.subBlock}"`,
                                              `-r ${to}`,
                                              `-S smtp=${HOST}`,
                                              '-S smtp-use-starttls',
                                              '-S smtp-auth=login',
                                              `-S smtp-auth-user=${USER}`,
                                              `-S smtp-auth-password=${PASS}`,
                                              FROM
                                              ], null, GLib.SpawnFlags.SEARCH_PATH, null);

const in_reader = new Gio.DataOutputStream({
        base_stream: new Gio.UnixOutputStream({fd: in_fd})
      });
      var feedRes = in_reader.put_string(msgObj.msgBlock, null);

      const out_reader = new Gio.DataInputStream({
        base_stream: new Gio.UnixInputStream({fd: out_fd})
      });
      const err_reader = new Gio.DataInputStream({
        base_stream: new Gio.UnixInputStream({fd: err_fd})
      });
      var out = out_reader.read_until("", null);
      var err = err_reader.read_until("", null);

      print(` > out : "${out}"`);
      print(` > res : "${res}"`);
      print(` > feedRes : "${feedRes}"`);
      print(` > err : "${err}"`);

err是0,而res只是true

我不知道输出应该是什么,但我没有收到可识别的错误,也没有电子邮件被发送……如何让我的应用程序发送电子邮件?派生邮件不是一个好办法吗?提前感谢你给我的任何指点。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-26 06:52:06

这里有几件事让你感到困惑,我想我可以弄清楚。

代码语言:javascript
运行
复制
await GLib.spawn_async_with_pipes(

GLib有它自己的异步函数的概念,当适用时,需要包装在与await关键字有效工作的承诺中。在这种情况下,GLib.spawn_async_with_pipes()并不像您想象的那样是异步的,但这是可以的,因为我们将使用更高级别的类Gio.Subprocess

代码语言:javascript
运行
复制
async function mail(msgObj, to, host, user, pass, cancellable = null) {
    try {
        let proc = new Gio.Subprocess({
            argv: ['mail',
                   '-V',
                   // Option switches and values are separate args
                   '-s', `"${msgObj.subBlock}"`,
                   '-r', `${to}`,
                   '-S', `smtp=${host}`,
                   '-S', 'smtp-use-starttls',
                   '-S', 'smtp-auth=login',
                   '-S', `smtp-auth-user=${user}`,
                   '-S', `smtp-auth-password=${pass}`,
                   FROM
            ],
            flags: Gio.SubprocessFlags.STDIN_PIPE |
                   Gio.SubprocessFlags.STDOUT_PIPE |
                   Gio.SubprocessFlags.STDERR_MERGE
        });
        // Classes that implement GInitable must be initialized before use, but
        // you could use Gio.Subprocess.new(argv, flags) which will call this for you
        proc.init(cancellable);

        // We're going to wrap a GLib async function in a Promise so we can
        // use it like a native JavaScript async function.
        //
        // You could alternatively return this Promise instead of awaiting it
        // here, but that's up to you.
        let stdout = await new Promise((resolve, reject) => {

            // communicate_utf8() returns a string, communicate() returns a
            // a GLib.Bytes and there are "headless" functions available as well
            proc.communicate_utf8_async(
                // This is your stdin, which can just be a JS string
                msgObj.msgBlock,

                // we've been passing this around from the function args; you can
                // create a Gio.Cancellable and call `cancellable.cancel()` to
                // stop the command or any other operation you've passed it to at
                // any time, which will throw an "Operation Cancelled" error.
                cancellable,

                // This is the GAsyncReady callback, which works like any other
                // callback, but we need to ensure we catch errors so we can
                // propagate them with `reject()` to make the Promise work
                // properly
                (proc, res) => {
                    try {
                        let [ok, stdout, stderr] = proc.communicate_utf8_finish(res);
                        // Because we used the STDERR_MERGE flag stderr will be
                        // included in stdout. Obviously you could also call
                        // `resolve([stdout, stderr])` if you wanted to keep both
                        // and separate them.
                        // 
                        // This won't affect whether the proc actually return non-
                        // zero causing the Promise to reject()
                        resolve(stdout);
                    } catch (e) {
                        reject(e);
                    }
                }
            );
        });

        return stdout;
    } catch (e) {
        // This could be any number of errors, but probably it will be a GError
        // in which case it will have `code` property carrying a GIOErrorEnum
        // you could use to programmatically respond to, if desired.
        logError(e);
    }
}

总的来说,Gio.Subprocess是一个更好的选择,但特别是对于不能将“输出”参数传递给函数的语言绑定。使用GLib.spawn_async_with_pipes时,你通常会传入NULL来防止打开任何你不想打开的管道,并始终确保关闭任何你不想要的管道。

Gio.Subprocess为你做了很多额外的工作,并确保文件描述符关闭,防止僵尸进程,为你设置子监视以及其他你真正不想担心的事情。它还具有获取IO流的便利函数,因此您不必自己包装fd,以及其他有用的功能。

我写了一本关于GJS异步编程的较长的入门读物,你可能会发现它对here很有帮助。您应该能够很快地浏览它,并且它试图澄清一些关于GLib异步、JavaScript异步和GLib主循环vs JS事件循环之间的关系的混淆。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54371576

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档