/*
* The following code will send a verification code to a player after they set their email with 'setemail'.
* After verifying their email the MUD can then be used to send other emails (password recovery, immortal note, etc).
*
* This was written for AckFUSS 4.4.1 but should port easily to any Diku-based game. Substitute char * fields for string
* fields and adjust as needed if you are compiling with gcc instead of g++.
*
* STEP 1:
* Add the defines for do_verify_email() and do_set_email() to your command table/headers like any other command.
*
* STEP 2:
* Add the following struct to your primary .h file
* struct email_data
* {
* bool verified;
* string address;
* string confirmation_code;
* };
* Then declare the following typedef with your other typedefs
* typedef struct email_data EMAIL_DATA;
* Finally, add it to your char_data or pc_data struct where applicable.
* NOTE: Be sure to make proper new/delete memory calls in your character create/delete routines.
* EMAIL_DATA *email;
*
* STEP 3:
* Add fields in your save/load player routines to save all the values of your new email_data struct.
*
* STEP 4:
* Adjust things to fit your game, such as mudnamecolor, the EMAIL_FILE logging, and monitor_chan notifications.
*
* STEP 5:
* Ensure your system is setup for command line email. You can test via your shell with the following:
* echo "This is the body text." | mail -s "Testing CLI Email" "your@email.com"
*
* STEP 6:
* Fix anything broken with your server's email daemon if you don't receive your email from step 4 :).
*
* Feel free to modify this code to suit your needs, and if you have a great improvement I wouldn't mind if you
* shared it with me either, if you're so inclined :D. All I ask is to give me credit for the code if you do
* choose to use it.
*
* --Kline (Matt Goff)
*/
DO_FUN(do_verify_email)
{
if ( IS_NPC( ch ) )
return;
if ( ch->pcdata->email->address.empty() )
{
ch->send( "You need to provide an email address first with setemail <address>.\r\n" );
return;
}
if ( ch->pcdata->email->verified )
{
ch->send( "You have already verified your email. If you wish to update your email, please use setemail <address>.\r\n" );
return;
}
if ( argument[0] == '\0' )
{
ch->send( "To verify your email address you must everify <code> using the code you received.\r\n" );
return;
}
if ( !str_cmp( argument, ch->pcdata->email->confirmation_code ) )
{
ch->send( "Thank you for verifying your email address.\r\n");
ch->pcdata->email->confirmation_code.clear();
ch->pcdata->email->verified = true;
snprintf( log_buf, MSL, "%s (%s) has verified their email address.", ch->get_name(), ch->pcdata->email->address.c_str() );
monitor_chan( log_buf, MONITOR_EMAIL );
return;
}
else
{
ch->send( "Invalid code. If you did not receive a validation code please reset your email using the setemail command.\r\n" );
return;
}
return;
}
DO_FUN(do_set_email)
{
char body[MSL], subject[MSL];
if ( IS_NPC( ch ) )
return;
if ( argument[0] == '\0' )
{
ch->send( "You didn't provide an email address. Syntax is setemail <email>.\r\n" );
return;
}
ch->pcdata->email->address = argument;
ch->pcdata->email->confirmation_code.clear();
ch->pcdata->email->confirmation_code = gen_rand_string(8);
ch->pcdata->email->verified = false;
ch->send( "An email has been sent to %s with a confirmation code. Please verify your address by typing everify <code> once your have received the email. If you do not receive an email, set your email again and a new code will be sent.\r\n", argument );
snprintf( subject, MSL, "%s Email Confirmation Code", mudnamenocolor );
snprintf( body, MSL, "<html>This email was used by a player of %s. If this was not you, please disregard it.<br><br>Confirmation code: <b>%s</b></html>", mudnamenocolor, ch->pcdata->email->confirmation_code.c_str() );
send_email( argument, subject, body, false, ch);
return;
}
bool send_email( const char *address, const char *subject, const char *body, bool validate, CHAR_DATA *ch )
{
char mailbuf[MSL];
FILE *fp;
if( IS_NPC(ch) ) /* Safety check for later --Kline */
ch = NULL;
if ( validate && ch != NULL && !ch->pcdata->email->verified )
{
snprintf( log_buf, MSL, "Unable to send email to %s (%s); email not verified.", ch->get_name(), ch->pcdata->email->address.c_str() );
monitor_chan( log_buf, MONITOR_EMAIL );
return false;
}
snprintf( mailbuf, MSL, "echo \"%s\" | mail -a \"Content-type: text/html;\" -s \"%s\" \"%s\"", body, subject, ch == NULL ? address : ch->pcdata->email->address.c_str() );
/*
* system() is if() encapsulated to suppress a warning. system() returns different results on different distros,
* so there is no reliable return value to check against. --Kline
*/
if ( system( mailbuf ) ) {}
if( ch == NULL )
snprintf( log_buf, MSL, "An email was sent to (%s) with subject (%s).", address, subject );
else
snprintf( log_buf, MSL, "An email was sent to %s (%s) with subject (%s).", ch->get_name(), ch->pcdata->email->address.c_str(), subject );
monitor_chan( log_buf, MONITOR_EMAIL );
if ( ( fp = file_open( EMAIL_FILE, "a" ) ) != NULL )
{
fprintf( fp, "%s :: %s\n", current_time_str(), mailbuf );
file_close( fp );
}
return true;
}
const char *gen_rand_string( int length )
{
int i, r;
char tmp[2];
static char output[MSL];
const char valid[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
srand ( current_time );
for ( i = 0; i < length; i++ )
{
r = rand() % strlen(valid);
snprintf( tmp, 2, "%c", valid[r] );
if ( i == 0 )
snprintf ( output, length+1, "%s", tmp );
else
strncat ( output, tmp, length+1 );
}
return output;
}
const char *current_time_str( void )
{
char *strtime;
static char output[MSL];
strtime = ctime( ¤t_time );
strtime[strlen( strtime ) - 1] = '\0';
snprintf( output, MSL, "%s", strtime );
return output;
}