diff --git a/addons/require-login.php b/addons/require-login.php
index 569dd49..4c29c0e 100644
--- a/addons/require-login.php
+++ b/addons/require-login.php
@@ -28,6 +28,7 @@ class CampTix_Require_Login extends CampTix_Addon {
 		add_filter( 'camptix_checkout_attendee_info',                 array( $this, 'add_unknown_attendee_info_stubs' ) );
 		add_filter( 'camptix_edit_info_cell_content',                 array( $this, 'show_buyer_attendee_status_instead_of_edit_link' ), 10, 2 );
 		add_filter( 'camptix_attendee_info_default_value',            array( $this, 'prepopulate_known_fields' ), 10, 5 );
+		add_action( 'camptix_ticket_emailed',                         array( $this, 'record_first_email_reminder' ) );
 
 		// wp-admin
 		add_filter( 'camptix_attendee_report_column_value_username',  array( $this, 'get_attendee_username_meta' ), 10, 2 );
@@ -48,6 +49,8 @@ class CampTix_Require_Login extends CampTix_Addon {
 		add_action( 'template_redirect',                              array( $this, 'block_unauthenticated_actions' ), 7 );    // before CampTix_Plugin->template_redirect()
 		add_filter( 'camptix_attendees_shortcode_query_args',         array( $this, 'hide_unconfirmed_attendees' ) );
 		add_filter( 'camptix_private_attendees_parameters',           array( $this, 'prevent_unknown_attendees_viewing_private_content' ) );
+		add_action( 'hourly',                                         array( $this, 'remind_unconfirmed_attendees' ) );
+		add_shortcode( 'ticket_holder_status',                        array( $this, 'email_template_shortcode_ticket_holder_status' ) );
 	}
 
 	/**
@@ -308,7 +311,7 @@ class CampTix_Require_Login extends CampTix_Addon {
 	 */
 	public function get_attendee_search_meta( $attendee_search_meta ) {
 		$attendee_search_meta[] = 'tix_username';
-		
+
 		return $attendee_search_meta;
 	}
 
@@ -353,6 +356,16 @@ class CampTix_Require_Login extends CampTix_Addon {
 			'callback_method' => 'field_textarea',
 		);
 
+		$templates['email_template_unconfirmed_attendee_reminder'] = array(
+			'title'           => __( 'Multiple Purchase Reminder (to unconfirmed attendees)', 'camptix' ),      // todo just use the same one they get when they registered?
+			'callback_method' => 'field_textarea',
+		);
+
+		$templates['email_template_unknown_attendee_reminder'] = array(
+			'title'           => __( 'Multiple Purchase Reminder (for unknown attendees)', 'camptix' ),
+			'callback_method' => 'field_textarea',
+		);
+
 		return $templates;
 	}
 
@@ -366,7 +379,9 @@ class CampTix_Require_Login extends CampTix_Addon {
 	public function custom_email_template_default_values( $options ) {
 		$options['email_template_multiple_purchase_receipt_unconfirmed_attendees'] = __( "Hi there!\n\nYou have purchased the following tickets:\n\n[receipt]\n\nYou can view and edit your order at any time before the event, by visiting the following link:\n\n[ticket_url]\n\nThe other attendees that you purchased tickets for will need to confirm their registration by visiting a link that was sent to them by e-mail.\n\nLet us know if you have any questions!", 'camptix' );
 		$options['email_template_multiple_purchase_unconfirmed_attendee']          = __( "Hi there!\n\nA ticket to [event_name] has been purchased for you by [buyer_full_name].\n\nPlease visit the following page and fill in your information to complete your registration:\n\n[ticket_url]\n\nLet us know if you have any questions!", 'camptix' );
+		$options['email_template_multiple_purchase_unconfirmed_attendee_reminder'] = __( "Hi there!\n\nThe ticket to [event_name] that [buyer_full_name] purchased for you has not yet been confirmed.\n\nTo confirm your ticket, please complete the form on the following page:\n\n[ticket_url]\n\nLet us know if you have any questions!", 'camptix' );
 		$options['email_template_multiple_purchase_unknown_attendee']              = __( "Hi there!\n\nThis e-mail is for the unknown attendee that you purchased a ticket for. When you decide who will be using the ticket, please forward the link below to them so that they can complete their registration.\n\n[ticket_url]\n\nLet us know if you have any questions!", 'camptix' );
+		$options['email_template_multiple_purchase_unknown_attendees_reminder']    = __( "Hi there!\n\nSome of the tickets that you purchased for [event_name] have not been claimed by their holders yet. Please review the summary below, and send the corresponding confirmation link to each ticket holder who has not yet claimed their ticket.\n\n[ticket_holder_status]\n\nLet us know if you have any questions!", 'camptix' );
 
 		return $options;
 	}
@@ -395,6 +410,16 @@ class CampTix_Require_Login extends CampTix_Addon {
 				}
 
 				break;
+			case 'email_template_unconfirmed_reminder':
+				$unknown_attendee_info = $this->get_unknown_attendee_info();
+
+				if ( $unknown_attendee_info['email'] == get_post_meta( $attendee->ID, 'tix_email', true ) ) {
+					$template = 'email_template_unknown_attendee_reminder';
+				} elseif ( self::UNCONFIRMED_USERNAME == get_post_meta( $attendee->ID, 'tix_username', true ) ) {
+					$template = 'email_template_unconfirmed_attendee_reminder';
+				}
+
+				break;
 		}
 
 		return $template;
@@ -581,6 +606,21 @@ class CampTix_Require_Login extends CampTix_Addon {
 	}
 
 	/**
+	 * Initialize the reminder timestamp for unconfirmed attendees.
+	 *
+	 * This fires when attendees are sent the initial e-mail upon successful registration. We will later want
+	 * to send them reminder e-mails if they haven't confirmed their ticket, but we don't want to do that if
+	 * they just registered yesterday, so we treat the ticket purchase timestamp as if it were the first reminder.
+	 *
+	 * @param int $attendee_id
+	 */
+	public function record_first_email_reminder( $attendee_id ) {
+		if ( self::UNCONFIRMED_USERNAME == get_post_meta( $attendee_id, 'tix_username', true ) ) {
+			update_post_meta( $attendee_id, 'tix_last_unconfirmed_reminder', time() );
+		}
+	}
+
+	/**
 	 * Define the unknown attendee info stubs
 	 *
 	 * @return array
@@ -785,6 +825,204 @@ class CampTix_Require_Login extends CampTix_Addon {
 
 		return $parameters;
 	}
-} // CampTix_Require_Login 
+
+	/**
+	 * Send reminders to the unconfirmed attendees
+	 *
+	 * TODO:
+	 * - get proper text for the subject and body for each situation;
+	 *
+	 * @return array
+	 */
+	public function remind_unconfirmed_attendees() {
+		/** @var $camptix CampTix_Plugin */
+		global $shortcode_tags, $camptix;
+
+		// todo maybe split this into at least 3 functions: determine if ready to send, send status for unknown attendees to buyer, send individual unconfirmed attendees to their email
+		// todo if they buy ticket 8 days before camp, don't send reminder on the 7th, wait at least 7? days since last reminder
+		// todo add batch email functionality to camptix proper, then just push the data you want here. probably already exists to some extent, so use it
+
+		// Set up a couple dates to use for calculations
+		$wordcamp                            = get_wordcamp_post();
+		$days_until_camp                     = floor( ( $wordcamp->meta['Start Date (YYYY-mm-dd)'][0] - time() ) / DAY_IN_SECONDS );
+		$unknown_attendee_info               = $this->get_unknown_attendee_info();
+		$camptix_options                     = $camptix->get_options();
+		$emails_sent                         = 0;
+		$max_emails_to_send                  = 35;
+		$transactions_with_unknown_attendees = array();
+
+		// Only send reminders once a week, but if the camp is happening this week and they still haven't registered, allow an extra one.
+		if ( $days_until_camp >= 7 ) {
+			$reminder_interval = 7 * DAY_IN_SECONDS;
+		} else {
+			$reminder_interval = 3 * DAY_IN_SECONDS;
+		}
+
+		// Remove all shortcodes before sending the e-mails, but bring them back later.
+		$this->removed_shortcodes = $shortcode_tags;
+		remove_all_shortcodes();
+
+		// setup shortcodes for these email templates
+		do_action( 'camptix_init_email_templates_shortcodes' );
+
+		$unconfirmed_attendees = get_posts( array(
+			'post_type'			=> 'tix_attendee',
+			'post_status'		=> array( 'pending', 'publish' ),
+			'posts_per_page'	=> 100,         // todo bigger? smaller? needs permenant comment explaining why it is what it is?
+			'meta_query'		=> array(
+				array(
+					'key'		=> 'tix_username',
+					'value'		=> self::UNCONFIRMED_USERNAME,
+					'compare'	=> '=',
+				),
+
+				array(
+					'key'       => 'tix_last_unconfirmed_reminder',
+					'value'     => time() - $reminder_interval,
+					'compare'   => '<',
+
+					/* todo will need to insert meta val when creating ticket, and manually insert for 2014.sf */
+				),
+			),
+		) );
+
+		$subject = sprintf( __( "%s Unconfirmed Ticket Reminder", 'camptix' ), $wordcamp->post_title );     // todo update subj
+
+		foreach ( $unconfirmed_attendees as $attendee ) {
+			$attendee_meta = get_post_custom( $attendee->ID );
+			$camptix->tmp( 'attendee_id', $attendee->ID );
+
+			if ( $emails_sent >= $max_emails_to_send ) {
+				break;
+			}
+
+			/*
+			 * We can't send e-mail to unknown attendees because we don't have their address,
+			 * so we'll send an e-mail to the buy later with the status of all their tickets
+			 */
+			if ( $unknown_attendee_info['email'] == $attendee_meta['tix_email'][0] ) {
+				$transactions_with_unknown_attendees[] = $attendee_meta['tix_payment_token'][0];
+				continue;
+			}
+
+			/*
+			doing this in mysql instead
+
+			$last_reminder_sent = empty( $attendee_meta['tix_last_unconfirmed_reminder'] ) ? strtotime( $attendee->post_date_gmt ) : $attendee_meta['tix_last_unconfirmed_reminder'];
+
+			// Don't nag attendees too often
+			if ( time() - $last_reminder_sent > $reminder_interval ) {
+				printf( '<p>skipping %s - last sent %s days ago', $attendee->ID, ( time() - $last_reminder_sent ) / DAY_IN_SECONDS );        // todo
+				continue;
+			}
+			*/
+
+			// Set notification vars
+			$camptix->tmp( 'ticket_url', $camptix->get_edit_attendee_link( $attendee->ID, $attendee_meta['tix_edit_token'][0] ) );
+
+			// If there is an email address for the unconfirmed attendee use it, else use the receipt email address
+			$send_to = $attendee_meta['tix_email'][0];     // todo test to confirm switching this didn't break it
+			$email_template = apply_filters( 'camptix_email_tickets_template', 'email_template_multiple_purchase_unconfirmed_attendee_reminder', $attendee );
+
+			$content = do_shortcode( $camptix_options[ $email_template ] );    // todo test b/c changed
+
+			printf( '<p>Sending unconfirmed %s', $attendee->post_title );
+			continue;
+
+			// Send message
+			if ( $camptix->wp_mail( $send_to, $subject, $content ) ) {
+				update_post_meta( $attendee->ID, 'tix_last_unconfirmed_reminder', time() );     // todo bcc yourself for the first few days to check that they look good. have to do this in mu plugin
+				$emails_sent++;
+			}
+
+		}
+
+		if ( $emails_sent < $max_emails_to_send ) {
+			$this->remind_unknown_attendees( array_unique( $transactions_with_unknown_attendees ), $camptix_options, $max_emails_to_send - $emails_sent );
+		}
+
+		// Bring the original shortcodes back.
+		$shortcode_tags = $this->removed_shortcodes;
+		$this->removed_shortcodes = array();
+
+	}
+
+	// todo
+	// send all for entire transaction, but don't send any for next transaction if above the limit
+	// already know they haven't been reminded recently
+	protected function remind_unknown_attendees( $transactions, $camptix_options, $number_to_send ) {
+		/** @var $camptix CampTix_Plugin */
+		global $camptix;
+		$emails_sent = 0;
+
+		foreach ( $transactions as $payment_token ) {
+			if ( $emails_sent >= $number_to_send ) {
+				break;
+			}
+
+			$attendees = get_posts( array(
+				'post_type'      => 'tix_attendee',
+				'post_status'    => array( 'pending', 'publish' ),
+				'posts_per_page' => -1,
+
+				'meta_query'     => array(
+					array(
+						'key'   => 'tix_payment_token',
+						'value' => $payment_token
+					),
+				),
+			) );
+
+			$ticket_holder_status = '';
+			foreach ( $attendees as $attendee ) {
+				if ( self::UNKNOWN_ATTENDEE_EMAIL ) {
+					$edit_token = get_post_meta( $attendee->ID, 'edit_token', true );
+
+					$confirmation_link = sprintf(
+						"\nConfirmation link: %s",
+						$camptix->get_edit_attendee_link( $attendee->ID, $edit_token )
+					);
+				} else {
+					$confirmation_link = '';
+				}
+
+				$ticket_holder_status .= sprintf(
+					"\nTicket %s: %s
+					%s\n",
+					1,
+					$attendee->post_title,
+					$confirmation_link
+				);
+			}
+			$camptix->tmp( 'ticket_holder_status', $ticket_holder_status );
+
+			$email_template = apply_filters( 'camptix_email_tickets_template', 'email_template_multiple_purchase_unknown_attendees_reminder', $attendee );
+			$content = do_shortcode( $camptix_options[ $email_template ] );    // todo test b/c changed
+
+
+			printf( '<p>sending unknown - %s', implode( ', ', wp_list_pluck( $attendees, 'post_title' ) ) );
+			continue;
+
+			if ( $camptix->wp_mail( $buyer_email, $subject, $content ) ) {
+				$emails_sent++;
+
+				foreach ( $attendees as $attendee ) {
+					update_post_meta( $attendee->ID, 'tix_last_unconfirmed_reminder', time() );     // todo bcc yourself for the first few days to check that they look good. have to do this in mu plugin
+				}
+			}
+		}
+	}
+
+	/**
+	 * Returns the ticket holder status
+	 */
+	function email_template_shortcode_ticket_holder_status( $atts ) {
+		/** @var $camptix CampTix_Plugin */
+		global $camptix;
+
+		return $camptix->tmp( 'ticket_holder_status' );
+	}
+
+} // CampTix_Require_Login
 
 camptix_register_addon( 'CampTix_Require_Login' );
