ares-openbsd/nall/smtp.hpp

181 行
4.3 KiB
C++

#pragma once
#include <nall/stdint.hpp>
#include <nall/string.hpp>
#include <nall/file.hpp>
#include <nall/location.hpp>
#include <nall/random.hpp>
#include <nall/encode/base64.hpp>
#if !defined(PLATFORM_WINDOWS)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#endif
namespace nall {
struct SMTP {
enum class Format : u32 { Plain, HTML };
auto server(string server, u16 port = 25) -> void;
auto from(string mail, string name = "") -> void;
auto to(string mail, string name = "") -> void;
auto cc(string mail, string name = "") -> void;
auto bcc(string mail, string name = "") -> void;
auto attachment(const u8* data, u32 size, string name) -> void;
auto attachment(string filename, string name = "") -> bool;
auto subject(string subject) -> void;
auto body(string body, Format format = Format::Plain) -> void;
auto send() -> bool;
auto message() -> string;
auto response() -> string;
#if defined(API_WINDOWS)
auto close(s32) -> s32;
SMTP();
#endif
private:
struct Information {
string server;
u16 port;
struct Contact {
string mail;
string name;
};
Contact from;
vector<Contact> to;
vector<Contact> cc;
vector<Contact> bcc;
struct Attachment {
vector<u8> buffer;
string name;
};
string subject;
string body;
Format format = Format::Plain;
vector<Attachment> attachments;
string message;
string response;
} info;
auto send(s32 sock, const string& text) -> bool;
auto recv(s32 sock) -> string;
auto boundary() -> string;
auto filename(const string& filename) -> string;
auto contact(const Information::Contact& contact) -> string;
auto contacts(const vector<Information::Contact>& contacts) -> string;
auto split(const string& text) -> string;
};
inline auto SMTP::server(string server, u16 port) -> void {
info.server = server;
info.port = port;
}
inline auto SMTP::from(string mail, string name) -> void {
info.from = {mail, name};
}
inline auto SMTP::to(string mail, string name) -> void {
info.to.append({mail, name});
}
inline auto SMTP::cc(string mail, string name) -> void {
info.cc.append({mail, name});
}
inline auto SMTP::bcc(string mail, string name) -> void {
info.bcc.append({mail, name});
}
inline auto SMTP::attachment(const u8* data, u32 size, string name) -> void {
vector<u8> buffer;
buffer.resize(size);
memcpy(buffer.data(), data, size);
info.attachments.append({std::move(buffer), name});
}
inline auto SMTP::attachment(string filename, string name) -> bool {
if(!file::exists(filename)) return false;
if(name == "") name = Location::file(filename);
auto buffer = file::read(filename);
info.attachments.append({std::move(buffer), name});
return true;
}
inline auto SMTP::subject(string subject) -> void {
info.subject = subject;
}
inline auto SMTP::body(string body, Format format) -> void {
info.body = body;
info.format = format;
}
inline auto SMTP::message() -> string {
return info.message;
}
inline auto SMTP::response() -> string {
return info.response;
}
inline auto SMTP::boundary() -> string {
PRNG::LFSR random;
random.seed(time(0));
string boundary;
for(u32 n = 0; n < 16; n++) boundary.append(hex(random.random(), 2L));
return boundary;
}
inline auto SMTP::filename(const string& filename) -> string {
string result;
for(auto& n : filename) {
if(n <= 32 || n >= 127) result.append("%", hex(n, 2L));
else result.append(n);
}
return result;
}
inline auto SMTP::contact(const Information::Contact& contact) -> string {
if(!contact.name) return contact.mail;
return {"\"", contact.name, "\" <", contact.mail, ">"};
}
inline auto SMTP::contacts(const vector<Information::Contact>& contacts) -> string {
string result;
for(auto& contact : contacts) {
result.append(this->contact(contact), "; ");
}
result.trimRight("; ", 1L);
return result;
}
inline auto SMTP::split(const string& text) -> string {
string result;
u32 offset = 0;
while(offset < text.size()) {
u32 length = min(76, text.size() - offset);
if(length < 76) {
result.append(text.slice(offset));
} else {
result.append(text.slice(offset, 76), "\r\n");
}
offset += length;
}
return result;
}
}
#if defined(NALL_HEADER_ONLY)
#include <nall/smtp.cpp>
#endif