mirror of
https://github.com/jetzig-framework/jetzig.git
synced 2025-05-14 22:16:08 +00:00
Merge pull request #64 from jetzig-framework/mailer-improvements
Allow mailers to modify mail template params
This commit is contained in:
commit
bd62f75cb8
@ -7,8 +7,8 @@
|
|||||||
.hash = "1220482f07f2bbaef335f20d6890c15a1e14739950b784232bc69182423520e058a5",
|
.hash = "1220482f07f2bbaef335f20d6890c15a1e14739950b784232bc69182423520e058a5",
|
||||||
},
|
},
|
||||||
.zmpl = .{
|
.zmpl = .{
|
||||||
.url = "https://github.com/jetzig-framework/zmpl/archive/4457eba50bd2eff3743601aa00adbffebcd4207a.tar.gz",
|
.url = "https://github.com/jetzig-framework/zmpl/archive/c14683521ca48c1de0a9b2d61dfb145e1bc4dac1.tar.gz",
|
||||||
.hash = "122001d661e534ef59fc20936330bb0c3068c8aaf1b7c60f9dde9e58d9a536918754",
|
.hash = "122093b741ef4aff151e916fc6005cb0c2aed747a34b77c0d4b45099ea2b561df9c7",
|
||||||
},
|
},
|
||||||
.jetkv = .{
|
.jetkv = .{
|
||||||
.url = "https://github.com/jetzig-framework/jetkv/archive/edfda9108c857dd5a04f87ae48667d3ed57612d9.tar.gz",
|
.url = "https://github.com/jetzig-framework/jetkv/archive/edfda9108c857dd5a04f87ae48667d3ed57612d9.tar.gz",
|
||||||
|
@ -8,7 +8,7 @@ const util = @import("../util.zig");
|
|||||||
/// Command line options for the `bundle` command.
|
/// Command line options for the `bundle` command.
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
optimize: enum { Debug, ReleaseFast, ReleaseSmall } = .ReleaseFast,
|
optimize: enum { Debug, ReleaseFast, ReleaseSmall } = .ReleaseFast,
|
||||||
arch: enum { x86_64, aarch64, default } = .default,
|
arch: enum { x86, x86_64, aarch64, default } = .default,
|
||||||
os: enum { linux, macos, windows, default } = .default,
|
os: enum { linux, macos, windows, default } = .default,
|
||||||
|
|
||||||
pub const meta = .{
|
pub const meta = .{
|
||||||
@ -190,6 +190,7 @@ fn zig_build_install(allocator: std.mem.Allocator, path: []const u8, options: Op
|
|||||||
|
|
||||||
try target_buf.append("-Dtarget=");
|
try target_buf.append("-Dtarget=");
|
||||||
switch (options.arch) {
|
switch (options.arch) {
|
||||||
|
.x86 => try target_buf.append("x86"),
|
||||||
.x86_64 => try target_buf.append("x86_64"),
|
.x86_64 => try target_buf.append("x86_64"),
|
||||||
.aarch64 => try target_buf.append("aarch64"),
|
.aarch64 => try target_buf.append("aarch64"),
|
||||||
.default => try target_buf.append(@tagName(builtin.cpu.arch)),
|
.default => try target_buf.append(@tagName(builtin.cpu.arch)),
|
||||||
|
@ -51,7 +51,7 @@ pub fn run(allocator: std.mem.Allocator, cwd: std.fs.Dir, args: [][]const u8, he
|
|||||||
\\// * env: Provides the following fields:
|
\\// * env: Provides the following fields:
|
||||||
\\// - logger: Logger attached to the same stream as the Jetzig server.
|
\\// - logger: Logger attached to the same stream as the Jetzig server.
|
||||||
\\// - environment: Enum of `{ production, development }`.
|
\\// - environment: Enum of `{ production, development }`.
|
||||||
\\pub fn run(allocator: std.mem.Allocator, params: *jetzig.data.Value, logger: jetzig.Logger) !void {
|
\\pub fn run(allocator: std.mem.Allocator, params: *jetzig.data.Value, env: jetzig.jobs.JobEnv) !void {
|
||||||
\\ _ = allocator;
|
\\ _ = allocator;
|
||||||
\\ _ = params;
|
\\ _ = params;
|
||||||
\\ // Job execution code goes here. Add any code that you would like to run in the background.
|
\\ // Job execution code goes here. Add any code that you would like to run in the background.
|
||||||
|
@ -39,45 +39,34 @@ pub fn run(allocator: std.mem.Allocator, cwd: std.fs.Dir, args: [][]const u8, he
|
|||||||
};
|
};
|
||||||
|
|
||||||
try mailer_file.writeAll(
|
try mailer_file.writeAll(
|
||||||
\\const std = @import("std");
|
|
||||||
\\const jetzig = @import("jetzig");
|
|
||||||
\\
|
|
||||||
\\// Default values for this mailer.
|
|
||||||
\\pub const defaults: jetzig.mail.DefaultMailParams = .{
|
|
||||||
\\ .from = "no-reply@example.com",
|
|
||||||
\\ .subject = "Default subject",
|
|
||||||
\\};
|
|
||||||
\\
|
|
||||||
\\// The `deliver` function is invoked every time this mailer is used to send an email.
|
\\// The `deliver` function is invoked every time this mailer is used to send an email.
|
||||||
\\// Use this function to modify mail parameters before the mail is delivered, or simply
|
\\// Use this function to set default mail params (e.g. a default `from` address or
|
||||||
\\// to log all uses of this mailer.
|
\\// `subject`) before the mail is delivered.
|
||||||
\\//
|
\\//
|
||||||
\\// To use this mailer from a request:
|
|
||||||
\\// ```
|
|
||||||
\\// const mail = request.mail("<mailer-name>", .{ .to = &.{"user@example.com"} });
|
|
||||||
\\// try mail.deliver(.background, .{});
|
|
||||||
\\// ```
|
|
||||||
\\// A mailer can provide two Zmpl templates for rendering email content:
|
\\// A mailer can provide two Zmpl templates for rendering email content:
|
||||||
\\// * `src/app/mailers/<mailer-name>/html.zmpl
|
\\// * `src/app/mailers/<mailer-name>/html.zmpl
|
||||||
\\// * `src/app/mailers/<mailer-name>/text.zmpl
|
\\// * `src/app/mailers/<mailer-name>/text.zmpl
|
||||||
\\//
|
\\//
|
||||||
\\// Arguments:
|
\\// Arguments:
|
||||||
\\// * allocator: Arena allocator for use during the mail delivery process.
|
\\// * allocator: Arena allocator for use during the mail delivery process.
|
||||||
\\// * mail: Mail parameters. Inspect or override any values assigned when the mail was created.
|
\\// * mail: Mail parameters (from, to, subject, etc.). Inspect or override any values
|
||||||
\\// * params: Params assigned to a mail (from a request, any values added to `data`). Params
|
\\// assigned when the mail was created.
|
||||||
\\// can be modified before email delivery.
|
\\// * data: Provides `data.string()` etc. for generating Jetzig Values.
|
||||||
|
\\// * params: Template data for `text.zmpl` and `html.zmpl`. Inherits all response data
|
||||||
|
\\// assigned in a view function and can be modified for email-specific content.
|
||||||
\\// * env: Provides the following fields:
|
\\// * env: Provides the following fields:
|
||||||
\\// - logger: Logger attached to the same stream as the Jetzig server.
|
\\// - logger: Logger attached to the same stream as the Jetzig server.
|
||||||
\\// - environment: Enum of `{ production, development }`.
|
\\// - environment: Enum of `{ production, development }`.
|
||||||
\\pub fn deliver(
|
\\pub fn deliver(
|
||||||
\\ allocator: std.mem.Allocator,
|
\\ allocator: std.mem.Allocator,
|
||||||
\\ mail: *jetzig.mail.MailParams,
|
\\ mail: *jetzig.mail.MailParams,
|
||||||
|
\\ data: *jetzig.data.Data,
|
||||||
\\ params: *jetzig.data.Value,
|
\\ params: *jetzig.data.Value,
|
||||||
\\ env: jetzig.jobs.JobEnv,
|
\\ env: jetzig.jobs.JobEnv,
|
||||||
\\) !void {
|
\\) !void {
|
||||||
\\ _ = allocator;
|
\\ _ = allocator;
|
||||||
|
\\ _ = data;
|
||||||
\\ _ = params;
|
\\ _ = params;
|
||||||
\\
|
|
||||||
\\ try env.logger.INFO("Delivering email with subject: '{?s}'", .{mail.get(.subject)});
|
\\ try env.logger.INFO("Delivering email with subject: '{?s}'", .{mail.get(.subject)});
|
||||||
\\}
|
\\}
|
||||||
\\
|
\\
|
||||||
|
@ -17,20 +17,23 @@ pub const defaults: jetzig.mail.DefaultMailParams = .{
|
|||||||
//
|
//
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// * allocator: Arena allocator for use during the mail delivery process.
|
// * allocator: Arena allocator for use during the mail delivery process.
|
||||||
// * mail: Mail parameters. Inspect or override any values assigned when the mail was created.
|
// * mail: Mail parameters (from, to, subject, etc.). Inspect or override any values
|
||||||
// * params: Params assigned to a mail (from a request, any values added to `data`). Params
|
// assigned when the mail was created.
|
||||||
// can be modified before email delivery.
|
// * data: Provides `data.string()` etc. for generating Jetzig Values.
|
||||||
|
// * params: Template data for `text.zmpl` and `html.zmpl`. Inherits all response data
|
||||||
|
// assigned in a view function and can be modified for email-specific content.
|
||||||
// * env: Provides the following fields:
|
// * env: Provides the following fields:
|
||||||
// - logger: Logger attached to the same stream as the Jetzig server.
|
// - logger: Logger attached to the same stream as the Jetzig server.
|
||||||
// - environment: Enum of `{ production, development }`.
|
// - environment: Enum of `{ production, development }`.
|
||||||
pub fn deliver(
|
pub fn deliver(
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
mail: *jetzig.mail.MailParams,
|
mail: *jetzig.mail.MailParams,
|
||||||
|
data: *jetzig.data.Data,
|
||||||
params: *jetzig.data.Value,
|
params: *jetzig.data.Value,
|
||||||
env: jetzig.jobs.JobEnv,
|
env: jetzig.jobs.JobEnv,
|
||||||
) !void {
|
) !void {
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
_ = params;
|
try params.put("email_message", data.string("Custom email message"));
|
||||||
|
|
||||||
try env.logger.INFO("Delivering email with subject: '{?s}'", .{mail.get(.subject)});
|
try env.logger.INFO("Delivering email with subject: '{?s}'", .{mail.get(.subject)});
|
||||||
}
|
}
|
||||||
|
@ -1 +1,2 @@
|
|||||||
<div>{{.message}}</div>
|
<div>{{.message}}</div>
|
||||||
|
<div>{{.email_message}}</div>
|
||||||
|
@ -1 +1,3 @@
|
|||||||
{{.message}}
|
{{.message}}
|
||||||
|
|
||||||
|
{{.email_message}}
|
||||||
|
@ -3,18 +3,14 @@ const jetzig = @import("jetzig");
|
|||||||
|
|
||||||
/// This example demonstrates usage of Jetzig's background jobs.
|
/// This example demonstrates usage of Jetzig's background jobs.
|
||||||
pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
||||||
|
// Prepare a job using `src/app/jobs/example.zig`.
|
||||||
// Create a new job using `src/app/jobs/example_job.zig`.
|
|
||||||
var job = try request.job("example");
|
var job = try request.job("example");
|
||||||
|
|
||||||
// Add a param `foo` to the job.
|
// Add a param `foo` to the job.
|
||||||
try job.params.put("foo", data.string("bar"));
|
try job.params.put("foo", data.string("bar"));
|
||||||
try job.params.put("id", data.integer(std.crypto.random.int(u32)));
|
try job.params.put("id", data.integer(std.crypto.random.int(u32)));
|
||||||
|
|
||||||
// Schedule the job for background processing. The job is added to the queue. When the job is
|
// Schedule the job for background processing.
|
||||||
// processed a new instance of `example_job` is created and its `run` function is invoked.
|
|
||||||
// All params are added above are available to the job by calling `job.params()` inside the
|
|
||||||
// `run` function.
|
|
||||||
try job.schedule();
|
try job.schedule();
|
||||||
|
|
||||||
return request.render(.ok);
|
return request.render(.ok);
|
||||||
|
@ -3,7 +3,7 @@ const jetzig = @import("jetzig");
|
|||||||
|
|
||||||
pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
||||||
var root = try data.object();
|
var root = try data.object();
|
||||||
try root.put("cached_value", try request.cache.get("example"));
|
try root.put("message", try request.cache.get("message"));
|
||||||
|
|
||||||
return request.render(.ok);
|
return request.render(.ok);
|
||||||
}
|
}
|
||||||
|
2
demo/src/app/views/cache/index.zmpl
vendored
2
demo/src/app/views/cache/index.zmpl
vendored
@ -1,3 +1,3 @@
|
|||||||
<div>
|
<div>
|
||||||
<span>Cached value: {{.cached_value}}</span>
|
<span>Cached value: {{.message}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,23 +6,25 @@ pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|||||||
|
|
||||||
// Fetch a string from the KV store. If it exists, store it in the root data object,
|
// Fetch a string from the KV store. If it exists, store it in the root data object,
|
||||||
// otherwise store a string value to be picked up by the next request.
|
// otherwise store a string value to be picked up by the next request.
|
||||||
if (try request.store.fetchRemove("example-key")) |capture| {
|
if (try request.store.get("example-key")) |capture| {
|
||||||
try root.put("stored_string", capture);
|
try root.put("stored_string", capture);
|
||||||
} else {
|
} else {
|
||||||
try root.put("stored_string", null);
|
try root.put("stored_string", null);
|
||||||
try request.store.put("example-key", data.string("example-value"));
|
try request.store.put("example-key", data.string("example-value"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Left-pop an item from the array and store it in the root data object. This will empty the
|
// Left-pop an item from an array and store it in the root data object. This will empty the
|
||||||
// array after multiple requests.
|
// array after multiple requests.
|
||||||
|
// If the array is empty or not found, append some new values to the array.
|
||||||
if (try request.store.popFirst("example-array")) |value| {
|
if (try request.store.popFirst("example-array")) |value| {
|
||||||
try root.put("popped", value);
|
try root.put("popped", value);
|
||||||
} else {
|
} else {
|
||||||
try root.put("popped", null);
|
|
||||||
// Store some values in an array in the KV store.
|
// Store some values in an array in the KV store.
|
||||||
try request.store.append("example-array", data.string("hello"));
|
try request.store.append("example-array", data.string("hello"));
|
||||||
try request.store.append("example-array", data.string("goodbye"));
|
try request.store.append("example-array", data.string("goodbye"));
|
||||||
try request.store.append("example-array", data.string("hello again"));
|
try request.store.append("example-array", data.string("hello again"));
|
||||||
|
|
||||||
|
try root.put("popped", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return request.render(.ok);
|
return request.render(.ok);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
<div>
|
<div>
|
||||||
<span>Your email has been sent!</span>
|
<span>Your email has been sent!</span>
|
||||||
|
<div>{{.message}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1 +0,0 @@
|
|||||||
<div>{{.data.test}}</div>
|
|
@ -1 +0,0 @@
|
|||||||
{{.data.test}}
|
|
@ -1 +0,0 @@
|
|||||||
<div>Hello</div>
|
|
@ -31,55 +31,55 @@ redirected: bool = false,
|
|||||||
rendered_multiple: bool = false,
|
rendered_multiple: bool = false,
|
||||||
rendered_view: ?jetzig.views.View = null,
|
rendered_view: ?jetzig.views.View = null,
|
||||||
start_time: i128,
|
start_time: i128,
|
||||||
store: ArenaStore,
|
store: RequestStore,
|
||||||
cache: ArenaStore,
|
cache: RequestStore,
|
||||||
|
|
||||||
/// Wrapper for KV store that uses the request's arena allocator for fetching values.
|
/// Wrapper for KV store that uses the request's arena allocator for fetching values.
|
||||||
pub const ArenaStore = struct {
|
pub const RequestStore = struct {
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
store: *jetzig.kv.Store,
|
store: *jetzig.kv.Store,
|
||||||
|
|
||||||
/// Put a String or into the key-value store.
|
/// Put a String or into the key-value store.
|
||||||
pub fn get(self: ArenaStore, key: []const u8) !?*jetzig.data.Value {
|
pub fn get(self: RequestStore, key: []const u8) !?*jetzig.data.Value {
|
||||||
return try self.store.get(try self.data(), key);
|
return try self.store.get(try self.data(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a String from the store.
|
/// Get a String from the store.
|
||||||
pub fn put(self: ArenaStore, key: []const u8, value: *jetzig.data.Value) !void {
|
pub fn put(self: RequestStore, key: []const u8, value: *jetzig.data.Value) !void {
|
||||||
try self.store.put(key, value);
|
try self.store.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove a String to from the key-value store and return it if found.
|
/// Remove a String to from the key-value store and return it if found.
|
||||||
pub fn fetchRemove(self: ArenaStore, key: []const u8) !?*jetzig.data.Value {
|
pub fn fetchRemove(self: RequestStore, key: []const u8) !?*jetzig.data.Value {
|
||||||
return try self.store.fetchRemove(try self.data(), key);
|
return try self.store.fetchRemove(try self.data(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove a String to from the key-value store.
|
/// Remove a String to from the key-value store.
|
||||||
pub fn remove(self: ArenaStore, key: []const u8) !void {
|
pub fn remove(self: RequestStore, key: []const u8) !void {
|
||||||
try self.store.remove(key);
|
try self.store.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Append a Value to the end of an Array in the key-value store.
|
/// Append a Value to the end of an Array in the key-value store.
|
||||||
pub fn append(self: ArenaStore, key: []const u8, value: *jetzig.data.Value) !void {
|
pub fn append(self: RequestStore, key: []const u8, value: *jetzig.data.Value) !void {
|
||||||
try self.store.append(key, value);
|
try self.store.append(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prepend a Value to the start of an Array in the key-value store.
|
/// Prepend a Value to the start of an Array in the key-value store.
|
||||||
pub fn prepend(self: ArenaStore, key: []const u8, value: *jetzig.data.Value) !void {
|
pub fn prepend(self: RequestStore, key: []const u8, value: *jetzig.data.Value) !void {
|
||||||
try self.store.prepend(key, value);
|
try self.store.prepend(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pop a String from an Array in the key-value store.
|
/// Pop a String from an Array in the key-value store.
|
||||||
pub fn pop(self: ArenaStore, key: []const u8) !?*jetzig.data.Value {
|
pub fn pop(self: RequestStore, key: []const u8) !?*jetzig.data.Value {
|
||||||
return try self.store.pop(try self.data(), key);
|
return try self.store.pop(try self.data(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Left-pop a String from an Array in the key-value store.
|
/// Left-pop a String from an Array in the key-value store.
|
||||||
pub fn popFirst(self: ArenaStore, key: []const u8) !?*jetzig.data.Value {
|
pub fn popFirst(self: RequestStore, key: []const u8) !?*jetzig.data.Value {
|
||||||
return try self.store.popFirst(try self.data(), key);
|
return try self.store.popFirst(try self.data(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn data(self: ArenaStore) !*jetzig.data.Data {
|
fn data(self: RequestStore) !*jetzig.data.Data {
|
||||||
const arena_data = try self.allocator.create(jetzig.data.Data);
|
const arena_data = try self.allocator.create(jetzig.data.Data);
|
||||||
arena_data.* = jetzig.data.Data.init(self.allocator);
|
arena_data.* = jetzig.data.Data.init(self.allocator);
|
||||||
return arena_data;
|
return arena_data;
|
||||||
@ -390,7 +390,10 @@ const RequestMail = struct {
|
|||||||
const text = if (self.mail_params.text) |text| mail_job.data.string(text) else null;
|
const text = if (self.mail_params.text) |text| mail_job.data.string(text) else null;
|
||||||
try mail_job.params.put("text", text);
|
try mail_job.params.put("text", text);
|
||||||
|
|
||||||
if (self.request.response_data.value) |value| try mail_job.params.put("params", value);
|
if (self.request.response_data.value) |value| try mail_job.params.put(
|
||||||
|
"params",
|
||||||
|
if (strategy == .now) try value.clone(self.request.allocator) else value,
|
||||||
|
);
|
||||||
|
|
||||||
switch (strategy) {
|
switch (strategy) {
|
||||||
.background => try mail_job.schedule(),
|
.background => try mail_job.schedule(),
|
||||||
|
@ -7,14 +7,24 @@ pub const JobDefinition = struct {
|
|||||||
runFn: *const fn (std.mem.Allocator, *jetzig.data.Value, JobEnv) anyerror!void,
|
runFn: *const fn (std.mem.Allocator, *jetzig.data.Value, JobEnv) anyerror!void,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Environment passed to all jobs.
|
||||||
pub const JobEnv = struct {
|
pub const JobEnv = struct {
|
||||||
|
/// The Jetzig server logger
|
||||||
logger: jetzig.loggers.Logger,
|
logger: jetzig.loggers.Logger,
|
||||||
|
/// The current server environment, `enum { development, production }`
|
||||||
environment: jetzig.Environment.EnvironmentName,
|
environment: jetzig.Environment.EnvironmentName,
|
||||||
|
/// All routes detected by Jetzig on startup
|
||||||
routes: []*const jetzig.Route,
|
routes: []*const jetzig.Route,
|
||||||
|
/// All mailers detected by Jetzig on startup
|
||||||
mailers: []const jetzig.MailerDefinition,
|
mailers: []const jetzig.MailerDefinition,
|
||||||
|
/// All jobs detected by Jetzig on startup
|
||||||
jobs: []const jetzig.JobDefinition,
|
jobs: []const jetzig.JobDefinition,
|
||||||
|
/// Global key-value store
|
||||||
store: *jetzig.kv.Store,
|
store: *jetzig.kv.Store,
|
||||||
|
/// Global cache
|
||||||
cache: *jetzig.kv.Store,
|
cache: *jetzig.kv.Store,
|
||||||
|
/// Global mutex - use with caution if it is necessary to guarantee thread safety/consistency
|
||||||
|
/// between concurrent job workers
|
||||||
mutex: *std.Thread.Mutex,
|
mutex: *std.Thread.Mutex,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,7 +34,9 @@ pub fn run(allocator: std.mem.Allocator, params: *jetzig.data.Value, env: jetzig
|
|||||||
.defaults = mailer.defaults,
|
.defaults = mailer.defaults,
|
||||||
};
|
};
|
||||||
|
|
||||||
try mailer.deliverFn(allocator, &mail_params, params, env);
|
var data = jetzig.data.Data.init(allocator);
|
||||||
|
|
||||||
|
try mailer.deliverFn(allocator, &mail_params, &data, params.get("params").?, env);
|
||||||
|
|
||||||
const mail = jetzig.mail.Mail.init(allocator, .{
|
const mail = jetzig.mail.Mail.init(allocator, .{
|
||||||
.subject = mail_params.get(.subject) orelse "(No subject)",
|
.subject = mail_params.get(.subject) orelse "(No subject)",
|
||||||
|
@ -4,6 +4,7 @@ const jetzig = @import("../../jetzig.zig");
|
|||||||
pub const DeliverFn = *const fn (
|
pub const DeliverFn = *const fn (
|
||||||
std.mem.Allocator,
|
std.mem.Allocator,
|
||||||
*jetzig.mail.MailParams,
|
*jetzig.mail.MailParams,
|
||||||
|
*jetzig.data.Data,
|
||||||
*jetzig.data.Value,
|
*jetzig.data.Value,
|
||||||
jetzig.jobs.JobEnv,
|
jetzig.jobs.JobEnv,
|
||||||
) anyerror!void;
|
) anyerror!void;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user