You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

客户端JavaScript发送邮件异常问题排查求助

客户端JS实现邮件发送功能的问题排查与解决

问题背景

尝试用客户端JavaScript实现发送邮件功能,点击按钮后新标签页显示空白(地址栏为about:blank)。将header设为全局变量后,首次点击仍有问题,第二次点击可正常工作,但控制台出现跨域权限报错。

相关代码

HTML

<button type="button" onclick="PrepEmail()">Contact Creator/Maintainer/Provider of This Data via email</button>

JavaScript

function PrepEmail() {
    var DBinfo, pnt, email, version, header;
    const ws = new WebSocket('ws://localhost:3000/');

    ws.onopen = function() {
        ws.send("DBInfo");
        ws.onmessage = function(e) {
            if (e.data == -1 || e.data == -2)
                alert ('Email address for Creator of DataBase not available.');
            else {
                DBinfo = e.data;
                pnt = DBinfo.indexOf("DBCreatorEmail =");
                if (pnt == -1)
                    alert ('Email address for Creator of DataBase not available.');
                else {
                    email = getData(DBinfo, pnt);
                    if (email == "not specified")
                        alert ('Email address for Creator of DataBase not available.');
                    else {
                        header = "mailto:";
                        header += email + "?subject=";
                        pnt = DBinfo.indexOf("DBName =");
                        if (pnt == -1)
                            header += "DataBase";
                        else {
                            header += getData(DBinfo, pnt);
                            pnt = DBinfo.indexOf("DBVersion =");
                            if (pnt != -1) {
                                version = getData(DBinfo, pnt);
                                header += " (" + version + ")";
                            }
                        }
                    }
                }
            }
        }
    }
    const terminationEvent = 'onpagehide' in self ? 'pagehide' : 'unload';
    window.addEventListener(terminationEvent, (event) => {
        if (event.persisted === false) {
            ws.onclose = function () { };
            ws.close();
        }
    });

    SendEmail(header);
}

function SendEmail (header) {
    const windowRef = window.open(header, '_blank');

    windowRef.focus();
    setTimeout(function() {
        if(!windowRef.document.hasFocus()) {
            windowRef.close();
        }
    }, 500);
}

function getData (DB, p) {
    var pos1 = DB.indexOf('"', p) + 1;
    var pos2 = DB.indexOf('"', pos1);
    var data = DB.substring(pos1, pos2);
    if (data == "")
        return ("not specified")
    else
        return (data);
}

WebSocket返回数据

DBName = "The Real DB"
DBVersion = "20230101"
DBCreator = "Joe Blow"
DBCreatorEmail = "jb@foo.com"

问题现象与报错

  1. 首次点击按钮:新标签页显示空白,地址栏为about:blank
  2. 将header设为全局变量后:首次点击仍空白,第二次点击可正常打开邮件客户端,但控制台报错:
Storage access automatically granted for origin “moz-nullprincipal:{c3a06e0d-3847-421d-b143-df87ff91029d}” on “http://999.999.9.999:8080”.
Uncaught DOMException: Permission denied to access property "document" on cross-origin object
    at SendEmail (http://999.999.9.999:8080/~devdir/Misc.html:65)
    at setTimeout handler*SendEmail (http://999.999.9.999:8080/~devdir/Misc.html:64)
    at PrepEmail (http://999.999.9.999:8080/~devdir/Misc.html:56)
    at onclick (http://999.999.9.999:8080/~devdir/Misc.html:1)

问题原因

  1. 异步执行顺序错误:WebSocket通信是异步操作,SendEmail(header)在ws.onmessage回调执行前就被调用,此时header未赋值,window.open传入undefined会打开about:blank。第二次点击时全局变量header已被第一次请求的回调赋值,所以能正常工作。
  2. 跨域权限限制:mailto:链接打开的是邮件客户端或浏览器的邮件处理页面,属于跨域上下文,尝试访问windowRef.document会触发浏览器同源策略,导致权限报错。

解决办法

1. 修正异步逻辑,在回调内调用SendEmail

将SendEmail(header)移动到ws.onmessage中header赋值完成的代码块内,确保只有当header正确生成后才执行打开邮件的操作:

function PrepEmail() {
    var DBinfo, pnt, email, version, header;
    const ws = new WebSocket('ws://localhost:3000/');

    ws.onopen = function() {
        ws.send("DBInfo");
        ws.onmessage = function(e) {
            if (e.data == -1 || e.data == -2)
                alert ('Email address for Creator of DataBase not available.');
            else {
                DBinfo = e.data;
                pnt = DBinfo.indexOf("DBCreatorEmail =");
                if (pnt == -1)
                    alert ('Email address for Creator of DataBase not available.');
                else {
                    email = getData(DBinfo, pnt);
                    if (email == "not specified")
                        alert ('Email address for Creator of DataBase not available.');
                    else {
                        header = "mailto:";
                        header += email + "?subject=";
                        pnt = DBinfo.indexOf("DBName =");
                        if (pnt == -1)
                            header += "DataBase";
                        else {
                            header += getData(DBinfo, pnt);
                            pnt = DBinfo.indexOf("DBVersion =");
                            if (pnt != -1) {
                                version = getData(DBinfo, pnt);
                                header += " (" + version + ")";
                            }
                        }
                        // 确保header生成后再调用SendEmail
                        SendEmail(header);
                    }
                }
            }
        }
    }
    const terminationEvent = 'onpagehide' in self ? 'pagehide' : 'unload';
    window.addEventListener(terminationEvent, (event) => {
        if (event.persisted === false) {
            ws.onclose = function () { };
            ws.close();
        }
    });
}

2. 移除跨域敏感的document访问代码

删除SendEmail中检查windowRef.document.hasFocus()的逻辑,避免触发跨域权限限制:

function SendEmail (header) {
    const windowRef = window.open(header, '_blank');
    if (windowRef) {
        windowRef.focus();
    } else {
        alert('无法打开邮件客户端,请检查浏览器弹窗设置');
    }
}

3. 可选:对mailto链接进行URL编码

为避免subject中的特殊字符导致链接失效,对subject部分进行URL编码:

// 生成subject时添加编码
const subject = pnt === -1 ? "DataBase" : `${getData(DBinfo, pnt)}${version ? ` (${version})` : ''}`;
header += encodeURIComponent(subject);

内容的提问来源于stack exchange,提问作者Marshall

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 10:34:53