25RCSID(
"$Id: 33183bb1aa6bd67d65ad266010757606f2a949b7 $")
 
   27#include <freeradius-devel/curl/base.h> 
   28#include <freeradius-devel/server/base.h> 
   29#include <freeradius-devel/server/cf_priv.h> 
   30#include <freeradius-devel/server/global_lib.h> 
   31#include <freeradius-devel/server/module_rlm.h> 
   32#include <freeradius-devel/server/tmpl_dcursor.h> 
   33#include <freeradius-devel/util/slab.h> 
   34#include <freeradius-devel/util/token.h> 
   36#include <freeradius-devel/unlang/call_env.h> 
   37#include <freeradius-devel/unlang/xlat_func.h> 
  192                *
out = curl_slist_append(*
out, 
vp->vp_strvalue);
 
  197        if (!elems_added) 
RDEBUG3(
"There were no %s elements found", dict_attr->name);
 
 
  207        fr_value_box_list_t 
const       *list = lists;
 
  210        size_t                          i, list_count = talloc_array_length(lists);
 
  212        for (i = 0; i < list_count; i++) {
 
  213                while ((vb = fr_value_box_list_next(list, vb))) {
 
  214                        *
out = curl_slist_append(*
out, vb->vb_strvalue);
 
 
  242        fr_value_box_list_t 
const       *list = lists;
 
  243        size_t                          i, list_count = talloc_array_length(lists);
 
  245        fr_sbuff_init_talloc(uctx, &sbuff, &sbuff_ctx, 256, SIZE_MAX);
 
  248        for (i = 0; i < list_count; i++) {
 
  249                while ((vb = fr_value_box_list_next(list, vb))) {
 
  260                                RERROR(
"Failed casting %pV to string", vb);
 
  271                RDEBUG2(
"No values to add to \"%s\" header", prefix);
 
 
  295        RDEBUG2(
"Trying to set attachment: %s", str);
 
  298                RDEBUG2(
"File attachments cannot be an absolute path");
 
  302        if (strncmp(str, 
"..", 2) == 0) {
 
  303                RDEBUG2(
"Cannot access values outside of template_directory");
 
  309                RDEBUG2(
"Cannot copy filename");
 
  314        part = curl_mime_addpart(mime);
 
  315        curl_mime_encoder(part, 
"base64");
 
  316        if (curl_mime_filedata(part, path_buffer->buff) != CURLE_OK) {
 
  317                REDEBUG2(
"Cannot add file attachment");
 
 
  337        fr_sbuff_init_talloc(uctx, &sbuff, &sbuff_ctx, 256, SIZE_MAX);
 
  344                                          strlen(
inst->envelope_address)) < 0)) {
 
  349        *
out = curl_slist_append(*
out, sbuff.buff);
 
 
  363        int             recipients_set = 0;
 
  375        if (recipients_set) {
 
  376                RDEBUG2(
"Recipients were generated from \"SMTP-Recipients\" and/or recipients in the config");
 
  377                return recipients_set;
 
  379        RDEBUG2(
"No addresses were found in \"SMTP-Recipients\"");
 
  396        RDEBUG2(
"%d recipients set", recipients_set);
 
  397        return recipients_set;
 
 
  412        if (fr_value_box_list_initialised(&call_env->
headers)) {
 
  413                while ((vb = fr_value_box_list_next(&call_env->
headers, vb))) {
 
  414                        RDEBUG2(
"Adding header \"%pV\"", vb);
 
  415                        uctx->
header = curl_slist_append(uctx->
header, vb->vb_strvalue);
 
  421                RDEBUG2(
"From: header could not be added");
 
  436                RDEBUG2(
"Header elements could not be added");
 
  441        if (
inst->set_date) {
 
  447        RDEBUG2(
"Finished generating the curl_slist for the header elements");
 
 
  454static size_t body_source(
char *ptr, 
size_t size, 
size_t nmemb, 
void *mail_ctx)
 
  465                RWARN(
"vp could not be found for the body element");
 
 
  501        curl_mime       *mime_body;
 
  503        int             body_elements = 0;
 
  515                MEM(part = curl_mime_addpart(mime_body));
 
  517                curl_mime_encoder(part, 
"8bit");
 
  518                curl_mime_data_cb(part, 
vp->vp_length, 
body_source, NULL, NULL, uctx);
 
  522        RDEBUG2(
"initialized %d body element part(s)", body_elements);
 
  530        MEM(part = curl_mime_addpart(mime));
 
  531        curl_mime_subparts(part, mime_body);
 
  532        MEM(curl_mime_type(part, 
"multipart/mixed") == CURLE_OK);
 
  533        uctx->
body_header = curl_slist_append(NULL, 
"Content-Disposition: inline"); 
 
  536        return body_elements;
 
 
  544        int                             attachments_set = 0;
 
  549        fr_value_box_list_t 
const       *list = call_env->
attachments;
 
  550        size_t                          i, list_count = talloc_array_length(call_env->
attachments);
 
  554        if (!
inst->template_dir) 
return 0;
 
  557        fr_sbuff_init_talloc(uctx, &path_buffer, &sbuff_ctx, talloc_array_length(
inst->template_dir) + 128, SIZE_MAX);
 
  563        if (
inst->template_dir[talloc_array_length(
inst->template_dir) - 2] != 
'/'){
 
  568        fr_sbuff_marker(&m, &path_buffer);
 
  571        for (i = 0; i < list_count; i++) {
 
  572                while ((vb = fr_value_box_list_next(list, vb))) {
 
  573                        attachments_set += 
str_to_attachments(uctx, mime, vb->vb_strvalue, vb->vb_length, &path_buffer, &m);
 
  580        return attachments_set;
 
 
  589        RDEBUG2(
"Forcefully cancelling pending SMTP request");
 
  592        if (ret != CURLM_OK) {
 
  593                RERROR(
"Failed removing curl handle from multi-handle: %s (%i)", curl_multi_strerror(ret), ret);
 
  597        smtp_slab_release(randle);
 
 
  618        curl_out_valid = curl_easy_getinfo(randle->
candle, CURLINFO_SSL_VERIFYRESULT, &curl_out);
 
  620        if (curl_out_valid == CURLE_OK){
 
  621                RDEBUG2(
"server certificate %s verified", curl_out ? 
"was" : 
"not");
 
  623                RDEBUG2(
"server certificate result not found");
 
  626        if (randle->
result != CURLE_OK) {
 
  627                CURLcode result = randle->
result;
 
  628                smtp_slab_release(randle);
 
  631                case CURLE_PEER_FAILED_VERIFICATION:
 
  632                case CURLE_LOGIN_DENIED:
 
  641        smtp_slab_release(randle);
 
 
  675                RERROR(
"Attribute \"smtp-body\" is required for smtp");
 
  680                RERROR(
"At least one of \"sender_address\" or \"envelope_address\" in the config, or \"SMTP-Sender-Address\" in the request is needed");
 
  682                if (randle) smtp_slab_release(randle);
 
  695                RDEBUG2(
"A handle could not be allocated for the request");
 
  704                .mime           = curl_mime_init(randle->
candle),
 
  713        if (call_env->
username.vb_strvalue) {
 
  716                if (!call_env->
password.vb_strvalue) 
goto skip_auth;
 
  719                RDEBUG3(
"Username and password set");
 
  725                                   (
inst->envelope_address ? 
inst->envelope_address :
 
  730                REDEBUG(
"At least one recipient is required to send an email");
 
  737                REDEBUG(
"The header slist could not be generated");
 
  751                REDEBUG(
"The body could not be generated");
 
  758                RDEBUG3(
"No files were attached to the email");
 
 
  788                RDEBUG(
"No 'username' was set for authentication - failing the request");
 
  793                RDEBUG(
"No 'username' was set for authentication - failing the request");
 
  817                smtp_slab_release(randle);
 
 
  838        if (randle->
result != CURLE_OK) {
 
  840                smtp_slab_release(randle);
 
  844        smtp_slab_release(randle);
 
 
  872                                    fr_value_box_list_t *
in)
 
  891                RERROR(
"A handle could not be allocated for the request");
 
  899                .mime           = curl_mime_init(randle->
candle),
 
  906        if (call_env->
username.vb_strvalue) {
 
  909                if (!call_env->
password.vb_strvalue) 
goto skip_auth;
 
  912                RDEBUG2(
"Username and password set");
 
  916        sender = 
inst->envelope_address ? 
inst->envelope_address : fr_value_box_list_head(call_env->
sender_address)->vb_strvalue;
 
  918        header_string = talloc_asprintf(call_env, 
"From: %s", sender);
 
  919        mail_ctx->
header = curl_slist_append(mail_ctx->
header, header_string);
 
  923        header_string = talloc_asprintf(call_env, 
"To: %s", to->vb_strvalue);
 
  924        mail_ctx->
header = curl_slist_append(mail_ctx->
header, header_string);
 
  926        header_string = talloc_asprintf(call_env, 
"Subject: %s", subject->vb_strvalue);
 
  927        mail_ctx->
header = curl_slist_append(mail_ctx->
header, header_string);
 
  929        if (fr_value_box_list_initialised(&call_env->
headers)) {
 
  930                while ((vb = fr_value_box_list_next(&call_env->
headers, vb))) {
 
  931                        RDEBUG2(
"Adding header \"%pV\"", vb);
 
  932                        mail_ctx->
header = curl_slist_append(mail_ctx->
header, vb->vb_strvalue);
 
  937        MEM(part = curl_mime_addpart(mail_ctx->
mime));
 
  938        if (curl_mime_encoder(part, 
"8bit") != CURLE_OK) {
 
  939                RERROR(
"Failed setting mime encoder");
 
  941                if (randle) smtp_slab_release(randle);
 
  946                if (curl_mime_data(part, body->vb_strvalue, body->vb_length) != CURLE_OK) {
 
  947                        RERROR(
"Failed adding email body");
 
  951                curl_mime_data(part, 
"", 0);
 
 
  975        inst->conn_config.reuse.num_children = 1;
 
 
  981#define SMTP_COMMON_CLEANUP \ 
  982        fr_mail_ctx_t   *mail_ctx = talloc_get_type_abort(randle->uctx, fr_mail_ctx_t); \ 
  983        if (mail_ctx->mime) curl_mime_free(mail_ctx->mime); \ 
  984        if (mail_ctx->header) curl_slist_free_all(mail_ctx->header); \ 
  985        if (mail_ctx->recipients) curl_slist_free_all(mail_ctx->recipients) 
 
 1010        randle->
uctx = mail_ctx;
 
 
 1029        mail_ctx->
randle = randle;
 
 1030        randle->
uctx = mail_ctx;
 
 1031        randle->
candle = curl_easy_init();
 
 
 1045#if CURL_AT_LEAST_VERSION(7,45,0) 
 1049#if CURL_AT_LEAST_VERSION(7,85,0) 
 
 1071        randle->
candle = curl_easy_init();
 
 
 1104                                                     inst, 
false, 
false))) {
 
 1105                ERROR(
"Connection handle pool instantiation failed");
 
 1110                                                     inst, 
false, 
true))) {
 
 1111                ERROR(
"Connection handle pool instantiation failed");
 
 1116        if (!mhandle) 
return -1;
 
 
 1167                                         &
FR_SBUFF_IN(to_parse, talloc_array_length(to_parse) - 1),
 
 
 1199                                     .pair.dflt = 
"SMTP-Recipients[*]", .pair.dflt_quote = 
T_BARE_WORD },
 
 1201                                    .pair.dflt = 
"SMTP-TO[*]", .pair.dflt_quote = 
T_BARE_WORD },
 
 1203                                    .pair.dflt = 
"SMTP-CC[*]", .pair.dflt_quote = 
T_BARE_WORD },
 
 1205                                    .pair.dflt = 
"SMTP-BCC[*]", .pair.dflt_quote = 
T_BARE_WORD },
 
 1207                                    .pair.dflt = 
"SMTP-Attachments[*]", .pair.dflt_quote = 
T_BARE_WORD },
 
 
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
void call_env_parsed_free(call_env_parsed_head_t *parsed, call_env_parsed_t *ptr)
Remove a call_env_parsed_t from the list of parsed call envs.
call_env_parsed_t * call_env_parsed_add(TALLOC_CTX *ctx, call_env_parsed_head_t *head, call_env_parser_t const *rule)
Allocate a new call_env_parsed_t structure and add it to the list of parsed call envs.
void call_env_parsed_set_tmpl(call_env_parsed_t *parsed, tmpl_t const *tmpl)
Assign a tmpl to a call_env_parsed_t.
#define CALL_ENV_TERMINATOR
#define FR_CALL_ENV_PARSE_OFFSET(_name, _cast_type, _flags, _struct, _field, _parse_field)
Specify a call_env_parser_t which writes out runtime results and the result of the parsing phase to t...
#define FR_CALL_ENV_METHOD_OUT(_inst)
Helper macro for populating the size/type fields of a call_env_method_t from the output structure typ...
call_env_parser_t const  * env
Parsing rules for call method env.
#define FR_CALL_ENV_SUBSECTION(_name, _name2, _flags, _subcs)
Specify a call_env_parser_t which defines a nested subsection.
@ CALL_ENV_FLAG_CONCAT
If the tmpl produced multiple boxes they should be concatenated.
@ CALL_ENV_FLAG_SUBSECTION
This is a subsection.
@ CALL_ENV_FLAG_SECRET
The value is a secret, and should not be logged.
@ CALL_ENV_FLAG_REQUIRED
Associated conf pair or section is required.
@ CALL_ENV_FLAG_PARSE_MISSING
If this subsection is missing, still parse it.
@ CALL_ENV_FLAG_BARE_WORD_ATTRIBUTE
bare words are treated as an attribute, but strings may be xlats.
@ CALL_ENV_FLAG_NULLABLE
Tmpl expansions are allowed to produce no output.
#define FR_CALL_ENV_SUBSECTION_FUNC(_name, _name2, _flags, _func)
Specify a call_env_parser_t which parses a subsection using a callback function.
#define FR_CALL_ENV_OFFSET(_name, _cast_type, _flags, _struct, _field)
Specify a call_env_parser_t which writes out runtime results to the specified field.
#define CONF_PARSER_TERMINATOR
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
Defines a CONF_PAIR to C data type mapping.
Common header for all CONF_* types.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
#define cf_canonicalize_error(_ci, _slen, _msg, _str)
#define cf_item_next(_parent, _curr)
#define cf_log_perr(_cf, _fmt,...)
fr_curl_handle_t * fr_curl_io_init(TALLOC_CTX *ctx, fr_event_list_t *el, bool multiplex)
#define FR_CURL_REQUEST_SET_OPTION(_x, _y)
CURLcode result
Result of executing the request.
#define FR_CURL_SET_OPTION(_x, _y)
uint64_t transfers
How many transfers are current in progress.
CURLM * mandle
The multi handle.
void * uctx
Private data for the module using the API.
int fr_curl_io_request_enqueue(fr_curl_handle_t *mhandle, request_t *request, fr_curl_io_request_t *creq)
Sends a request using libcurl.
CURL * candle
Request specific handle.
Uctx data for timer and I/O functions.
Structure representing an individual request being passed to curl for processing.
#define fr_dbuff_used(_dbuff_or_marker)
Return the number of bytes remaining between the start of the dbuff or marker and the current positio...
#define fr_dbuff_init(_out, _start, _len_or_end)
Initialise an dbuff for encoding or decoding.
#define fr_dbuff_remaining(_dbuff_or_marker)
Return the number of bytes remaining between the dbuff or marker and the end of the buffer.
#define fr_dbuff_in_memcpy_partial(_out, _in, _inlen)
Copy at most _inlen bytes into the dbuff.
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
fr_dict_attr_t const  ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const  ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
#define DICT_AUTOLOAD_TERMINATOR
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
#define GLOBAL_LIB_TERMINATOR
Structure to define how to initialise libraries with global configuration.
static xlat_action_t smtp_send_xlat(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Xlat to send simple emails.
int fr_curl_response_certinfo(request_t *request, fr_curl_io_request_t *randle)
int fr_curl_easy_tls_init(fr_curl_io_request_t *randle, fr_curl_tls_t const *conf)
global_lib_autoinst_t fr_curl_autoinst
conf_parser_t fr_curl_conn_config[]
conf_parser_t fr_curl_tls_config[]
#define DEBUG_ENABLED3
True if global debug level 1-3 messages are enabled.
#define REDEBUG2(fmt,...)
static void * item(fr_lst_t const *lst, fr_lst_index_t idx)
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_BOOL
A truth value.
void * env_data
Per call environment data.
module_instance_t const  * mi
Instance of the module being instantiated.
void * thread
Thread specific instance data.
void * rctx
Resume ctx that a module previously set.
fr_event_list_t * el
Event list to register any IO handlers and timers against.
void * thread
Thread instance data.
module_instance_t const  * mi
Instance of the module being instantiated.
#define MODULE_CTX(_mi, _thread, _env_data, _rctx)
Wrapper to create a module_ctx_t as a compound literal.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for instantiation calls.
Temporary structure to hold arguments for thread_instantiation calls.
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
module_t common
Common fields presented by all modules.
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
#define RETURN_UNLANG_INVALID
#define RETURN_UNLANG_RCODE(_rcode)
#define RETURN_UNLANG_FAIL
#define RETURN_UNLANG_REJECT
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_INVALID
The module considers the request invalid.
@ RLM_MODULE_FAIL
Module failed, don't reply.
static const call_env_method_t auth_env
struct curl_slist * recipients
static int header_source(fr_mail_ctx_t *uctx, rlm_smtp_t const *inst, rlm_smtp_env_t const *call_env)
fr_value_box_list_t headers
Entries to add to email header.
fr_value_box_list_t * bcc_addrs
The address(es) used for the Bcc: header.
global_lib_autoinst_t const  *const rlm_smtp_lib[]
static unlang_action_t smtp_io_module_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Callback to process response of SMTP server.
static int generate_from_header(fr_mail_ctx_t *uctx, struct curl_slist **out, rlm_smtp_t const *inst, rlm_smtp_env_t const *call_env)
Generate the From: header.
static int value_box_list_to_slist(struct curl_slist **out, fr_value_box_list_t const *lists)
Transform an array of value box lists to entries in a CURL slist.
static int smtp_persist_conn_alloc(fr_curl_io_request_t *randle, UNUSED void *uctx)
static const call_env_method_t smtp_call_env_xlat
static int value_box_list_to_header(fr_mail_ctx_t *uctx, struct curl_slist **out, fr_value_box_list_t const *lists, const char *prefix)
Converts an array of value box lists to a curl_slist with a prefix.
fr_value_box_t username
Value to use for user name.
static int attachments_source(fr_mail_ctx_t *uctx, curl_mime *mime, rlm_smtp_t const *inst, rlm_smtp_env_t const *call_env)
static void smtp_xlat_signal(xlat_ctx_t const *xctx, request_t *request, fr_signal_t action)
static int smtp_persist_conn_init(fr_curl_io_request_t *randle, void *uctx)
smtp_slab_list_t * slab_persist
Slab list for persistent connections.
static int smtp_conn_common_init(fr_curl_io_request_t *randle, rlm_smtp_t const *inst)
fr_curl_io_request_t * randle
static fr_dict_attr_t const  * attr_smtp_body
static const call_env_method_t method_env
static int smtp_onetime_request_cleanup(fr_curl_io_request_t *randle, UNUSED void *uctx)
static fr_dict_t const  * dict_freeradius
fr_value_box_t password
Password for authenticated mails.
fr_dict_attr_autoload_t rlm_smtp_dict_attr[]
fr_time_delta_t timeout
Timeout for connection and server response.
static int recipients_source(fr_mail_ctx_t *uctx, rlm_smtp_env_t const *call_env)
fr_dict_autoload_t rlm_smtp_dict[]
fr_curl_conn_config_t conn_config
Reusable CURL handle config.
tmpl_t * username_tmpl
tmpl expanded to populate username
static void smtp_io_module_signal(module_ctx_t const *mctx, request_t *request, UNUSED fr_signal_t action)
char const  * uri
URI of smtp server.
fr_value_box_t username
User to authenticate as when sending emails.
fr_value_box_t password
Value to use for password.
static int mod_bootstrap(module_inst_ctx_t const *mctx)
struct curl_slist * header
tmpl_t * password_tmpl
tmpl expanded to populate password
static int smtp_header_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_ctx_t const *cec, call_env_parser_t const *rule)
static fr_dict_attr_t const  * attr_smtp_header
static int smtp_persist_request_cleanup(fr_curl_io_request_t *randle, UNUSED void *uctx)
fr_value_box_list_t * cc_addrs
The address(es) used for the Cc: header.
fr_value_box_list_t * to_addrs
The address(es) used for the To: header.
#define SMTP_COMMON_CLEANUP
static int body_init(fr_mail_ctx_t *uctx, curl_mime *mime)
fr_value_box_list_t headers
Entries to add to email header.
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
struct curl_slist * body_header
static unlang_action_t mod_authenticate(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static unlang_action_t mod_mail(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static int smtp_onetime_conn_alloc(fr_curl_io_request_t *randle, UNUSED void *uctx)
fr_value_box_list_t * sender_address
The address(es) used to generate the From: header.
fr_value_box_t password
Password for authenticated mails.
char const  * envelope_address
The address used to send the message.
static int str_to_attachments(fr_mail_ctx_t *uctx, curl_mime *mime, char const *str, size_t len, fr_sbuff_t *path_buffer, fr_sbuff_marker_t *m)
fr_value_box_list_t * recipient_addrs
The address(es) used as recipients. Overrides elements in to, cc and bcc.
tmpl_t * username_tmpl
The tmpl used to produce the above.
static int smtp_onetime_conn_init(fr_curl_io_request_t *randle, void *uctx)
tmpl_t * username_tmpl
The tmpl used to produce the above.
static size_t body_source(char *ptr, size_t size, size_t nmemb, void *mail_ctx)
static xlat_arg_parser_t const smtp_xlat_args[]
char const  * template_dir
The directory that contains all email attachments.
fr_value_box_t username
User to authenticate as when sending emails.
fr_curl_tls_t tls
Used for handled all tls specific curl components.
static int da_to_slist(fr_mail_ctx_t *uctx, struct curl_slist **out, const fr_dict_attr_t *dict_attr)
static const conf_parser_t module_config[]
static int smtp_mail_ctx_free(fr_mail_ctx_t *mail_ctx)
fr_value_box_list_t * attachments
List of files to attach.
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
static int mod_instantiate(module_inst_ctx_t const *mctx)
fr_curl_handle_t * mhandle
Thread specific multi handle.
smtp_slab_list_t * slab_onetime
Slab list for onetime use connections.
static xlat_action_t smtp_send_xlat_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
fr_value_box_list_t * sender_address
The address(es) used to generate the From: header.
Call environment for SMTP authentication.
Call environment for sending emails.
Call environment for sending simple emails using an xlat.
ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
ssize_t fr_sbuff_in_bstrncpy(fr_sbuff_t *sbuff, char const *str, size_t len)
Copy bytes into the sbuff up to the first \0.
ssize_t fr_sbuff_in_bstrcpy_buffer(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
#define fr_sbuff_set(_dst, _src)
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_buff(_sbuff_or_marker)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define fr_sbuff_in_char(_sbuff,...)
Talloc sbuff extension structure.
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
size_t inst_size
Size of the module's instance data.
void * data
Module's instance data.
void * boot
Data allocated during the boostrap phase.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Named methods exported by a module.
int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules))
Attempt to resolve functions and attributes in xlats and attribute references.
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
#define tmpl_is_data(vpt)
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
#define tmpl_needs_resolving(vpt)
Similar to tmpl_rules_t, but used to specify parameters that may change during subsequent resolution ...
Optional arguments passed to vp_tmpl functions.
fr_signal_t
Signals that can be generated/processed by request signal handlers.
@ FR_SIGNAL_CANCEL
Request has been cancelled.
#define FR_SLAB_FUNCS(_name, _type)
Define type specific wrapper functions for slabs and slab elements.
#define FR_SLAB_TYPES(_name, _type)
Define type specific wrapper structs for slabs and slab elements.
unlang_action_t unlang_module_yield(request_t *request, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
eap_aka_sim_process_conf_t * inst
#define fr_time()
Allow us to arbitrarily manipulate time.
fr_dict_t const  * dict_def
Default dictionary to use with unqualified attribute references.
Stores an attribute, a value and various bits of other data.
#define talloc_get_type_abort_const
size_t fr_time_strftime_local(fr_sbuff_t *out, fr_time_t time, char const *fmt)
Copy a time string (local timezone) to an sbuff.
static int64_t fr_time_delta_to_msec(fr_time_delta_t delta)
A time delta, a difference in time measured in nanoseconds.
xlat_action_t unlang_xlat_yield(request_t *request, xlat_func_t resume, xlat_func_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
uint8_t required
Argument must be present, and non-empty.
#define XLAT_ARGS(_list,...)
Populate local variables with value boxes from the input list.
#define XLAT_ARG_PARSER_TERMINATOR
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition for a single argument consumend by an xlat function.
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
fr_sbuff_parse_rules_t const  * value_parse_rules_quoted[T_TOKEN_LAST]
Parse rules for quoted strings.
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
Convert one type of fr_value_box_t to another in place.
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
static size_t char ** out
void * rctx
Resume context.
void * env_data
Expanded call env data.
module_ctx_t const  * mctx
Synthesised module calling ctx.
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
void xlat_func_call_env_set(xlat_t *x, call_env_method_t const *env_method)
Register call environment of an xlat.