🍱
Apollo serverから、mailする(メール送信)
概要:
Apollo serverから、メールする例になります。
- トークン検証の為、mongoDbを使う例になります。
構成
- apollo-server-express
- nodemailer
- GraphQL
- mongoDB
参考のコード
準備
- smtp 設定, config.ts
SMTP_HOST, PORT, USER, PASSWORD, from mail ADDRESS
config.ts
SMTP_HOST : "host123.example.com",
SMTP_PORT : 465,
SMTP_SECURE : true,
SMTP_AUTH_USER : "user123",
SMTP_AUTH_PASS : "123",
SEND_MAIL_ADDRESS : "from123@example.com"
-
mongoDB, token保存
-
config.ts : MONGODB_URL ,MONGODB_DB_NAME set require
mongoDB atlas , user, password, cluster , host, dbName
config.ts
MONGODB_URL: 'mongodb+srv://user123:<pass123>@cluster999.sample123.net/test',
MONGODB_DB_NAME: 'test',
GraphQL
- Query
type Query {
getToken : String
}
- Mutation
type Mutation {
sendMail(token: String, to_mail: String, title: String, body: String ): String
}
GraphQLテスト
- token発行
query {
getToken
}
- mail 送信
token: 取得したトークン
to_mail: 送信先メール
mutation {
sendMail(token: "W1bOAIoP-friD9ub41UBHCFADr0rsaGnXpAA" ,
to_mail: "hoge@example.com"
, title: "title-test", body: "body-123")
}
-
送信処理
-
改行コードはエラーの為、送信時にBRタグ変換する例です。
-
メール送信前にBRタグから、改行[\r\n] に逆変換しています。
/src/lib/LibMail.ts
LibMail.ts
const LibMail = {
sendMail :async function(args: IArgs){
try {
console.log(args);
const valid = await LibCsrf.validToken(args);
const receiverEmailAddress = args.to_mail;
console.log(Config.SMTP_HOST);
console.log(Config.SMTP_PORT);
console.log(Config.SMTP_AUTH_USER);
console.log(Config.SMTP_AUTH_PASS);
console.log(Config.SEND_MAIL_ADDRESS);
let transporter = mailer.createTransport({
host: Config.SMTP_HOST,
port: Config.SMTP_PORT,
secure: Config.SMTP_SECURE,
auth: {
user: Config.SMTP_AUTH_USER,
pass: Config.SMTP_AUTH_PASS,
},
});
let body = args.body;
body = body.replace(/<br \/>/gi, '\r\n');
let info = await transporter.sendMail({
from: Config.SEND_MAIL_ADDRESS,
to: receiverEmailAddress,
subject: args.title,
text: body,
});
console.log("Message sent: %s", info.messageId);
console.log("Preview URL: %s", mailer.getTestMessageUrl(info));
return "OK";
} catch (err) {
console.error(err);
throw new Error('Error , sendMail');
}
},
}
export default LibMail;
- 受信確認, gmailで確認した例(下記画面)
フロント参考/ Remix
- 参考コード
- メール画面
- 送信画面: mail.tsx
/app/routes/mail.tsx
mail.tsx
export default function Page() {
console.log(Config);
const keyUid = Config.COOKIE_KEY_USER_ID;
// state
const [message, setMessage] = useState("");
const [messageError, setMessageError] = useState("");
const [token, setToken] = useState("");
useEffect(() => {
(async() => {
const data = await client.query({
query: gql`
query {
getToken
}
`,
fetchPolicy: "network-only"
});
console.log(data.data.getToken);
setToken(data.data.getToken);
})()
},[])
let onClick = async function(){
console.log("#onClick");
console.log(token);
const mail = document.querySelector<HTMLInputElement>('#mail');
const title = document.querySelector<HTMLInputElement>('#title');
const body = document.querySelector<HTMLInputElement>('#body');
let bodyText = body.value;
bodyText = bodyText.replace(/\r?\n/g, '<br />');
console.log(bodyText);
const result = await client.mutate({
mutation:gql`
mutation {
sendMail(token: "${token}" ,
to_mail: "${mail.value}"
, title: "${title.value}", body: "${bodyText}")
}
`
});
console.log(result.data);
if(result.data.sendMail !== 'OK'){
setMessageError("Error, Send mail");
}else{
setMessage("Success, Send mail");
}
}
return (
<div className="remix__page">
{ message ?
<div className="alert alert-success" role="alert">{message}</div>
: <div />
}
{ messageError ?
<div className="alert alert-danger" role="alert">{messageError}</div>
: <div /> }
<main>
<h2>Mail Send</h2>
<hr className="my-1" />
<div className="col-sm-6">
<label>
<div>mail:</div>
<input type="text" className="form-control" name="mail" id="mail" />
</label>
</div>
<div className="col-sm-6">
<label>
<div>Title:</div>
<input className="form-control" type="text" name="title" id="title" />
</label>
</div>
<hr className="my-1" />
<div className="col-sm-8">
<label>
<div>Body-Text:</div>
<textarea className="form-control" rows={8} name="body" id="body"></textarea>
</label>
</div>
<hr className="my-1" />
<button onClick={() => onClick()} className="btn btn-primary">Mail-Send
</button>
<hr />
{/*
*/}
</main>
</div>
);
}
....
Discussion