srctree

Gregory Mullen parent 7a248d8b 1b5592cb
add more mailer code

build.zig added: 141, removed: 5, total 136
@@ -70,12 +70,20 @@ pub fn build(b: *std.Build) void {
 
// Partner Binaries
const mailer = b.addExecutable(.{
.name = "mailer",
.name = "srctree-mailer",
.root_source_file = b.path("src/mailer.zig"),
.target = target,
.optimize = optimize,
});
b.installArtifact(mailer);
 
const send_email = b.addRunArtifact(mailer);
send_email.step.dependOn(b.getInstallStep());
const send_email_step = b.step("email", "send an email");
send_email_step.dependOn(&send_email.step);
if (b.args) |args| {
send_email.addArgs(args);
}
}
 
//fn compileTemplatesStruct(b: *std.Build, target: std.Build.ResolvedTarget) *std.Build.Step {
 
filename was Deleted added: 141, removed: 5, total 136
@@ -0,0 +1,7 @@
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (no) (never) (100)
# ==========================================================================
 
srctree unix - n n - - pipe
flags=DRhu argv=/usr/bin/srctree-mailer receive ${sender} ${recipient}
 
src/mailer.zig added: 141, removed: 5, total 136
@@ -1,9 +1,118 @@
const std = @import("std");
const Allocator = std.mem.Allocator;
const eql = std.mem.eql;
const startsWith = std.mem.startsWith;
 
fn usage() !void {
std.debug.print("TODO write usage/help text\n", .{});
}
 
pub const Server = struct {
host: []const u8,
port: u16,
 
stream: ?std.net.Stream = null,
 
pub fn connect(srv: *Server, a: Allocator) !void {
std.debug.assert(srv.stream == null);
srv.stream = try std.net.tcpConnectToHost(a, srv.host, srv.port);
}
 
fn sendBody(srv: *Server, msg: Message) !void {
const stream = srv.stream orelse return error.StreamInvalid;
var buffer: [0xffff]u8 = undefined;
const format: []const u8 =
\\From: {s}
\\To: {s}
\\Subject: {s}
\\
\\{s}
\\
;
const data = try std.fmt.bufPrint(&buffer, format, .{
msg.from,
msg.to.?,
msg.subject,
msg.body,
});
try stream.writeAll(data);
try stream.writeAll("\r\n.\r\n");
}
 
pub fn deliver(srv: *Server, msg: Message) !bool {
const stream = srv.stream orelse return error.StreamInvalid;
defer stream.close();
defer srv.stream = null;
 
var buffer: [0xFFFF]u8 = undefined;
var answer = buffer[0..try stream.read(&buffer)];
if (!startsWith(u8, answer, "220 ")) return error.UnexpectedMessage;
 
try stream.writeAll("HELO 98.42.94.105\r\n");
answer = buffer[0..try stream.read(&buffer)];
if (!startsWith(u8, answer, "250 ")) {
std.debug.print("answer: {s}\n", .{answer});
return error.UnexpectedMessage;
}
 
try stream.writeAll("MAIL FROM:");
try stream.writeAll(msg.from);
try stream.writeAll("\r\n");
answer = buffer[0..try stream.read(&buffer)];
std.debug.print("answer: {s}\n", .{answer});
if (!startsWith(u8, answer, "250 ")) {
return error.UnexpectedMessage;
}
 
try stream.writeAll("RCPT TO:");
try stream.writeAll(msg.to.?);
try stream.writeAll("\r\n");
answer = buffer[0..try stream.read(&buffer)];
std.debug.print("answer: {s}\n", .{answer});
if (!startsWith(u8, answer, "250 ")) {
return error.UnexpectedMessage;
}
 
try stream.writeAll("DATA\r\n");
answer = buffer[0..try stream.read(&buffer)];
std.debug.print("answer: {s}\n", .{answer});
if (!startsWith(u8, answer, "354 ")) {
return error.UnexpectedMessage;
}
try srv.sendBody(msg);
answer = buffer[0..try stream.read(&buffer)];
std.debug.print("answer: {s}\n", .{answer});
if (!startsWith(u8, answer, "250 ")) {
return error.UnexpectedMessage;
}
 
try stream.writeAll("QUIT\r\n");
answer = buffer[0..try stream.read(&buffer)];
std.debug.print("answer: {s}\n", .{answer});
if (!startsWith(u8, answer, "221 ")) {
return error.UnexpectedMessage;
}
 
return false;
}
};
 
pub const Address = []const u8;
pub const Subject = []const u8;
pub const Body = []const u8;
 
pub const Message = struct {
from: Address,
subject: Subject,
body: Body,
to: ?Address,
};
 
pub fn send(a: Allocator, srv: *Server, msg: Message) !void {
try srv.connect(a);
_ = try srv.deliver(msg);
}
 
fn receive() !void {
var stdin = std.io.getStdIn();
const in_reader = stdin.reader();
@@ -44,9 +153,21 @@ pub fn main() !void {
}
}
 
const a = std.heap.page_allocator;
if (std.mem.eql(u8, action, "send")) {
std.log.err("send not implemented", .{});
std.process.exit(1);
var server: Server = .{
.host = "mail.gr.ht",
.port = 587,
};
 
send(a, &server, .{
.from = "<mailer@gr.ht>",
.subject = "This is a test email",
.body = "",
.to = "<someuser@srctree.gr.ht>",
}) catch std.process.exit(1);
return;
} else if (std.mem.eql(u8, action, "receive")) {
std.log.err("receive not implemented (but good luck!)", .{});
try receive();