diff --git a/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java b/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java
index 748088e412c573a7a332ab6ca0ccc227efc16652..39f4d5c76bbb07a3f563ba7d5b0bce38a7b6baf7 100644
--- a/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java
+++ b/src/main/java/org/olat/course/editor/CourseAccessAndProperties.java
@@ -37,6 +37,7 @@ public class CourseAccessAndProperties {
 	private boolean canCopy;
 	private boolean canReference;
 	private boolean canDownload;	
+	private Boolean confirmationEmail;
 	
 	private List<OfferAccess> offerAccess;
 	private List<OfferAccess> deletedOfferAccess;
@@ -127,4 +128,12 @@ public class CourseAccessAndProperties {
 	public void setCanDownload(boolean canDownload) {
 		this.canDownload = canDownload;
 	}
+
+	public Boolean getConfirmationEmail() {
+		return confirmationEmail;
+	}
+
+	public void setConfirmationEmail(Boolean confirmationEmail) {
+		this.confirmationEmail = confirmationEmail;
+	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/editor/PublishProcess.java b/src/main/java/org/olat/course/editor/PublishProcess.java
index 0b59b5c73ec586317f8e6f6853630fac2068feb1..6446b40e37c282a3c81e95273330403b32560331 100644
--- a/src/main/java/org/olat/course/editor/PublishProcess.java
+++ b/src/main/java/org/olat/course/editor/PublishProcess.java
@@ -80,6 +80,7 @@ import org.olat.repository.controllers.EntryChangedEvent;
 import org.olat.repository.controllers.EntryChangedEvent.Change;
 import org.olat.repository.manager.CatalogManager;
 import org.olat.resource.accesscontrol.ACService;
+import org.olat.resource.accesscontrol.Offer;
 import org.olat.resource.accesscontrol.OfferAccess;
 import org.olat.resource.references.Reference;
 import org.olat.resource.references.ReferenceManager;
@@ -700,7 +701,7 @@ public class PublishProcess {
 		return publishTreeModel;
 	}
 
-	public void changeGeneralAccess(Identity author, int access, boolean membersOnly){
+	public void changeGeneralAccess(Identity author, int access, boolean membersOnly) {
 		RepositoryManager.getInstance().setAccess(repositoryEntry, access, membersOnly);
 		MultiUserEvent modifiedEvent = new EntryChangedEvent(repositoryEntry, author, Change.modifiedAtPublish, "publish");
 		CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(modifiedEvent, repositoryEntry);
@@ -718,6 +719,16 @@ public class PublishProcess {
 		// 1: add new and update existing offerings
 		ACService acService = CoreSpringFactory.getImpl(ACService.class);
 		for (OfferAccess newLink : offerAccess) {
+			if(accessAndProps.getConfirmationEmail() != null) {
+				Offer offer = newLink.getOffer();
+				boolean confirmation = accessAndProps.getConfirmationEmail().booleanValue();
+				if(offer.isConfirmationEmail() != confirmation) {
+					offer.setConfirmationEmail(confirmation);
+					if(offer.getKey() != null) {
+						offer = acService.save(offer);
+					}
+				}
+			}
 			acService.saveOfferAccess(newLink);
 		}
 		// 2: remove offerings not available anymore
@@ -777,6 +788,7 @@ public class PublishProcess {
 			this.skippableNodes = new ArrayList<CourseEditorTreeNode>();
 		}
 
+		@Override
 		public void visit(INode node) {
 			/*
 			 * DO NOT add or delete nodes via editorTreeModel, .....................
@@ -787,10 +799,10 @@ public class PublishProcess {
         // root node changed and published
         CourseNode clone = (CourseNode)XStreamHelper.xstreamClone(cetn.getCourseNode());
         resultingCourseRun.setRootNode(clone);
-        editorModelModifiedNodes.add(cetn);// TODO:pb: Review	Change to fic OLAT-1644
+        editorModelModifiedNodes.add(cetn);
         return;
 			}
-      if (cetn == root) { // TODO:pb: Review Change to fix OLAT-1644
+      if (cetn == root) {
       	// root node
         CourseNode clone = (CourseNode)XStreamHelper.xstreamClone(cetn.getCourseNode());
         resultingCourseRun.setRootNode(clone);
@@ -818,7 +830,6 @@ public class PublishProcess {
 					// already published, add it as it is. Silent "re-publish"
 					addNodeTo(resultingCourseRun, cetn);
         } else {
-          // TODO:pb:REVIEW Change to fix OLAT-1644
         	// changed in edit but not published => take old from existingRun
         	addNodeTo(resultingCourseRun, existingRun.getNode(cetn.getIdent()), cetn);
         }
@@ -908,7 +919,6 @@ public class PublishProcess {
 			parentClone.addChild(clone);
 		}
 
-    //	 TODO:pb:REVIEW Change to fix OLAT-1644
 		/**
 		 * @param newRunStruct
 		 * @param cetn
@@ -926,19 +936,15 @@ public class PublishProcess {
 		/**
 		 * flat list of all CourseEditorTreeNodes starting from root
 		 * 
-		 * @param root
+		 * @param treeNode
 		 * @param rootNodeWithSubtree
 		 */
-		private void collectSubTreeNodesStartingFrom(CourseEditorTreeNode root, List<CourseEditorTreeNode> rootNodeWithSubtree) {
-			for (int i = 0; i < root.getChildCount(); i++) {
-				CourseEditorTreeNode node = (CourseEditorTreeNode)root.getChildAt(i);
+		private void collectSubTreeNodesStartingFrom(CourseEditorTreeNode treeNode, List<CourseEditorTreeNode> rootNodeWithSubtree) {
+			for (int i = 0; i < treeNode.getChildCount(); i++) {
+				CourseEditorTreeNode node = (CourseEditorTreeNode)treeNode.getChildAt(i);
 				rootNodeWithSubtree.add(node);
 				collectSubTreeNodesStartingFrom(node, rootNodeWithSubtree);
 			}
 		}
 	}// end nested class
-
-
-	
-	
 }
diff --git a/src/main/java/org/olat/course/editor/PublishStep01AccessForm.java b/src/main/java/org/olat/course/editor/PublishStep01AccessForm.java
index 5f92779af49c5e841f17edeea65cf98819bf1239..71014ca9b89b27cfb8c3bfba3ffca37950fc214d 100644
--- a/src/main/java/org/olat/course/editor/PublishStep01AccessForm.java
+++ b/src/main/java/org/olat/course/editor/PublishStep01AccessForm.java
@@ -28,6 +28,7 @@ import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FormLink;
+import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
 import org.olat.core.gui.components.form.flexible.elements.SelectionElement;
 import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
 import org.olat.core.gui.components.form.flexible.impl.Form;
@@ -82,6 +83,8 @@ public class PublishStep01AccessForm extends StepFormBasicController {
 			RepositoryEntryAllowToLeaveOptions.never.name()
 		};
 	
+	private static final String[] onKeys = new String[] { "on" };
+	
 	private SingleSelection leaveEl;
 	
 	private RepositoryEntry entry;
@@ -104,7 +107,7 @@ public class PublishStep01AccessForm extends StepFormBasicController {
 	private static final String MEMBERSONLY_KEY = "m";
 	private String[] publishedKeys;
 	
-	
+	private MultipleSelectionElement confirmationEmailEl;
 	private List<FormLink> addMethods = new ArrayList<>();
 	private List<OfferAccess> offerAccess = new ArrayList<>();
 	private List<OfferAccess> deletedOfferAccess = new ArrayList<>();
@@ -171,6 +174,11 @@ public class PublishStep01AccessForm extends StepFormBasicController {
 		
 		accessProperties.setOfferAccess(offerAccess);
 		accessProperties.setDeletedOfferAccess(deletedOfferAccess);
+		if(confirmationEmailEl.isVisible()) {
+			accessProperties.setConfirmationEmail(confirmationEmailEl.isAtLeastSelected(1));
+		} else {
+			accessProperties.setConfirmationEmail(null);
+		}
 					
 		addToRunContext("accessAndProperties", accessProperties);	
 		
@@ -310,12 +318,25 @@ public class PublishStep01AccessForm extends StepFormBasicController {
 			accessLayout.contextPut("methods", addMethods);
 		}
 		
+		String[] onValues = new String[] { "" };
+		confirmationEmailEl = uifactory.addCheckboxesHorizontal("confirmation.email", accessLayout, onKeys, onValues);
+		confirmationEmailEl.addActionListener(FormEvent.ONCHANGE);
+		confirmationEmailEl.setVisible(false);
+
 		String confPage = velocity_root + "/configuration_list.html";
 		confControllerContainer = FormLayoutContainer.createCustomFormLayout("conf-controllers", getTranslator(), confPage);
 		accessLayout.add(confControllerContainer);
 		
 		loadConfigurations();
 		
+		boolean confirmationEmail = false;
+		for(AccessInfo info:confControllers) {
+			confirmationEmail |= info.getLink().getOffer().isConfirmationEmail();
+		}
+		if(confirmationEmail) {
+			confirmationEmailEl.select(onKeys[0], true);
+		}
+		
 		confControllerContainer.contextPut("confControllers", confControllers);
 		
 		confControllerContainer.contextPut("emptyConfigGrantsFullAccess", Boolean.valueOf(emptyConfigGrantsFullAccess));		
@@ -351,6 +372,14 @@ public class PublishStep01AccessForm extends StepFormBasicController {
 			delLink.setIconLeftCSS("o_icon o_icon-fw o_icon_delete_item");
 			confControllerContainer.add(delLink.getName(), delLink);
 		}
+		updateConfirmationEmail();
+	}
+	
+	private void updateConfirmationEmail() {
+		if(confirmationEmailEl.isVisible() != !confControllers.isEmpty()) {
+			confirmationEmailEl.setVisible(!confControllers.isEmpty());
+			accessLayout.setDirty(true);
+		}
 	}
 	
 	public class AccessInfo {
@@ -504,6 +533,12 @@ public class PublishStep01AccessForm extends StepFormBasicController {
 		} else if(addMethods.contains(source)) {
 			AccessMethod method = (AccessMethod)source.getUserObject();
 			addMethod(ureq, method);
+		} else if(confirmationEmailEl == source) {
+			for(AccessInfo info:confControllers) {
+				if(!offerAccess.contains(info.getLink())) {
+					offerAccess.add(info.getLink());
+				}
+			}
 		} else if (source instanceof FormLink) {
 			FormLink button = (FormLink)source;
 			String cmd = button.getCmd();
@@ -515,6 +550,7 @@ public class PublishStep01AccessForm extends StepFormBasicController {
 					deletedOfferAccess.add(deleteOffer);			
 				}
 				confControllers.remove(infos);
+				updateConfirmationEmail();
 				fireEvent(ureq, Event.CHANGED_EVENT);
 			} else if("edit".equals(cmd)) {
 				AccessInfo infos = (AccessInfo)source.getUserObject();
diff --git a/src/main/java/org/olat/course/editor/_content/access_configuration.html b/src/main/java/org/olat/course/editor/_content/access_configuration.html
index 0047566062bd6fad59505d6ed0513823ae76a52a..e530afecc3a5027d9e48c322bb1a87186aaa6bae 100644
--- a/src/main/java/org/olat/course/editor/_content/access_configuration.html
+++ b/src/main/java/org/olat/course/editor/_content/access_configuration.html
@@ -12,6 +12,12 @@
 		#if ($off_info) <div class="o_info">$off_info</div> #end
 	</div></div>
 #end
+	#if($r.visible("confirmation.email"))
+	<div class="form-group">
+		<label class="control-label col-sm-3">$r.translate("confirmation.email")</label>
+		<div class="col-sm-9">$r.render("confirmation.email")</div>
+	</div>
+	#end
 	<div class="form-group">
 		<label class="control-label col-sm-3">$r.translate("ac.methods.label") $r.render("acMethodsLabelHelp")</label>
 		<div class="col-sm-9">$r.render("conf-controllers")</div>
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupMailing.java b/src/main/java/org/olat/group/manager/BusinessGroupMailing.java
index 36d9c811f9fd4d78ed0e93c1e10323ad73ce5e95..4168d1e3a48f8560fb5747aeae3bc817bfd1ebbf 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupMailing.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupMailing.java
@@ -126,7 +126,12 @@ public class BusinessGroupMailing {
 
 		MailTemplate template = mailing == null ? null : mailing.getTemplate();
 		if(mailing == null || mailing.getTemplate() == null) {
-			template = getDefaultTemplate(type, group, ureqIdentity);
+			//booking by myself
+			if(type != null && type == MailType.addParticipant && ureqIdentity != null && ureqIdentity.equals(identity)) {
+				template = BGMailHelper.createAddMyselfMailTemplate(group, ureqIdentity);
+			} else {
+				template = getDefaultTemplate(type, group, ureqIdentity);
+			}
 		} else if(group != null && template.getContext() != null && needTemplateEnhancement(template)) {
 			BusinessGroupService businessGroupService = CoreSpringFactory.getImpl(BusinessGroupService.class);
 			List<RepositoryEntryShort> repoEntries = businessGroupService.findShortRepositoryEntries(Collections.singletonList(group), 0, -1);
diff --git a/src/main/java/org/olat/group/ui/edit/BusinessGroupEditAccessController.java b/src/main/java/org/olat/group/ui/edit/BusinessGroupEditAccessController.java
index 8c726fdf7b17349dd0d1ef8c6f17bd0dc85c9bce..2217d7905be61e614a7130e328a3a98c77810ebf 100644
--- a/src/main/java/org/olat/group/ui/edit/BusinessGroupEditAccessController.java
+++ b/src/main/java/org/olat/group/ui/edit/BusinessGroupEditAccessController.java
@@ -24,7 +24,6 @@ import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
-import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
@@ -38,7 +37,7 @@ import org.olat.resource.accesscontrol.ui.AccessConfigurationController;
 /**
  * 
  * Description:<br>
- * Add a check box to the standard access control controller
+ * Wrapper for the resource's access control.
  * 
  * <P>
  * Initial Date:  26 avr. 2011 <br>
@@ -75,22 +74,11 @@ public class BusinessGroupEditAccessController extends FormBasicController {
 		setFormTitle("accesscontrol.title");
 		setFormDescription("accesscontrol_group.desc");
 		setFormContextHelp("Group Administration#gruppensystem_buchung_ag");
+		formLayout.setElementCssClass("o_block_large_bottom");
 
 		if(configController != null) {
 			formLayout.add(configController.getInitialFormItem());
 		}
-		
-		if(configController != null && !managed) {
-			uifactory.addSpacerElement("spacer1", formLayout, false);
-		}
-		
-		if(!managed) {
-			final FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttonLayout", getTranslator());
-			buttonGroupLayout.setRootForm(mainForm);
-			formLayout.add(buttonGroupLayout);
-			
-			uifactory.addFormSubmitButton("save", formLayout);
-		}
 	}
 	
 	public void updateBusinessGroup(BusinessGroup businessGroup) {
@@ -109,10 +97,7 @@ public class BusinessGroupEditAccessController extends FormBasicController {
 
 	@Override
 	protected void formOK(UserRequest ureq) {
-		if(configController != null) {
-			configController.formOK(ureq);
-		}
-		fireEvent(ureq, Event.DONE_EVENT);
+		//
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/repository/RepositoryMailing.java b/src/main/java/org/olat/repository/RepositoryMailing.java
index 559fca1b8a049004efdb9f8927cada8607017e70..7c73d2bf7216e102b789380fb40b2cc4ee0e7936 100644
--- a/src/main/java/org/olat/repository/RepositoryMailing.java
+++ b/src/main/java/org/olat/repository/RepositoryMailing.java
@@ -74,6 +74,19 @@ public class RepositoryMailing {
 		return createMailTemplate(re, actor, subjectKey, bodyKey);
 	}
 	
+	/**
+	 * The mail template when adding users to a course.
+	 * 
+	 * @param re
+	 * @param actor
+	 * @return the generated MailTemplate
+	 */
+	public static MailTemplate createAddAutoParticipantMailTemplate(RepositoryEntry re, Identity actor) {
+		String subjectKey = "notification.mail.added.auto.subject";
+		String bodyKey = "notification.mail.added.auto.body";
+		return createMailTemplate(re, actor, subjectKey, bodyKey);
+	}
+	
 	/**
 	 * The mail template when adding tutors to a course.
 	 * 
@@ -119,6 +132,8 @@ public class RepositoryMailing {
 		switch(type) {
 			case addParticipant:
 				return createAddParticipantMailTemplate(re, ureqIdentity);
+			case addParticipantItself:
+				return createAddAutoParticipantMailTemplate(re, ureqIdentity);
 			case addTutor:
 				return createAddTutorMailTemplate(re, ureqIdentity);
 			case addOwner:
@@ -131,7 +146,7 @@ public class RepositoryMailing {
 		return null;
 	}
 
-	protected static void sendEmail(Identity ureqIdentity, Identity identity, RepositoryEntry re,
+	public static void sendEmail(Identity ureqIdentity, Identity identity, RepositoryEntry re,
 			Type type, MailPackage mailing) {
 		
 		if(mailing != null && !mailing.isSendEmail()) {
@@ -181,7 +196,8 @@ public class RepositoryMailing {
 		addTutor,
 		removeTutor,
 		addOwner,
-		removeOwner
+		removeOwner,
+		addParticipantItself
 	}
 	
 	private static MailTemplate createMailTemplate(RepositoryEntry re, Identity actor, String subjectKey, String bodyKey) {
diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties
index f25e518daa8cd227e249de38041cdbf777c21266..b1a602c46540480aa1acedf7d791c599d88b4598 100644
--- a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties
@@ -384,6 +384,8 @@ no.lifecycle=Keine Einschr\u00E4nkung
 no.catalog.entries=Diese Resource wurde noch nicht im Katalog registriert. \r\n\r\n Verwenden Sie den "In Katalog einf\u00FCgen" Button in der Toolbar, um die Resource auf einer bestimmten Katalog-Ebenen hinzuzuf\u00FCgen. Der Katalog erlaubt es dem Benutzer je nach Zugriffskonfiguration nach bestimmten Eintr\u00E4gen zu suchen. Sie k\u00F6nnen die Resource auf mehreren Katalog-Ebenen hinzuf\u00FCgen.
 info.catalog.entries=Verwenden Sie den "In Katalog einf\u00FCgen" Button in der Toolbar, um die Resource auf einer bestimmten Katalog-Ebenen hinzuzuf\u00FCgen. Der Katalog erlaubt es dem Benutzer je nach Zugriffskonfiguration nach bestimmten Eintr\u00E4gen zu suchen. Sie k\u00F6nnen die Resource auf mehreren Katalog-Ebenen hinzuf\u00FCgen.
 nomembers=XXX No members
+notification.mail.added.auto.body=*** Das ist eine automatisch generierte Nachricht. Bitte antworten Sie nicht auf diese Nachricht *** \n\nSie haben sich f\u00FCr den folgenden Kurs angemeldet\: \n\nKursname\: $coursename\nBeschreibung\: $coursedescription\nZugang\: $courseurl
+notification.mail.added.auto.subject=$\:notification.mail.added.subject
 notification.mail.added.body=*** Das ist eine automatisch generierte Nachricht. Bitte antworten Sie nicht auf diese Nachricht *** \n\nSie wurden von {0} {1} ({2}) in einen Kurs eingeladen\: \n\nKursname\: $coursename\nBeschreibung\: $coursedescription\nZugang\: $courseurl\n\nBei Fragen kontaktieren Sie bitte {0} {1} ({2}).
 notification.mail.added.subject=Kurs $coursename 
 notification.mail.removed.body=*** Das ist eine automatisch generierte Nachricht. Bitte antworten Sie nicht auf diese Nachricht *** \n\nSie wurden von {0} {1} ({2}) aus dem Kurs ausgetragen\: \n\nKursname\: $coursename\nBeschreibung\: $coursedescription\n\nBei Fragen kontaktieren Sie bitte {0} {1} ({2}).
diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties
index c2a87e54010a7bd99e288dc35f80d5ca08abefa4..19026de10963c68967c64893efb76b1de13bc14a 100644
--- a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties
@@ -381,6 +381,8 @@ no.lifecycle=No limitation
 no.catalog.entries=This resource has not been added to the catalog yet. \r\n\r\n Use the "Add to catalog" button in the toolbar above to add the resource to a specific level in the catalog. The catalog allows users to browse for available resources depending on th resource access configuration. You can add the resource to multiple catalog levels.
 info.catalog.entries=Use the "Add to catalog" button in the toolbar above to add the resource to a specific level in the catalog. The catalog allows users to browse for available resources depending on th resource access configuration. You can add the resource to multiple catalog levels. 
 nomembers=XXX No members
+notification.mail.added.auto.body=*** This is an automatically generated message. Please do not answer to this message *** \r\n\r\nYou registered you to the following course\:\r\n\r\nCourse name\: $coursename\r\nDescription\: $coursedescription\nLink\: $courseurl
+notification.mail.added.auto.subject=$\:notification.mail.added.subject
 notification.mail.added.body=*** This is an automatically generated message. Please do not answer to this message *** \r\n\r\nYou have been added by {0} {1} ({2}) to a course\:\r\n\r\nCourse name\: $coursename\r\nDescription\: $coursedescription\nLink\: $courseurl\n\nIf you have questions regarding this action, please contact {0} {1} ({2}).
 notification.mail.added.subject=Course $coursename
 notification.mail.removed.body=*** This is an automatically generated message. Please do not answer to this message *** \r\n\r\nYou have been removed by {0} {1} ({2}) from a course\:\r\n\r\nCourse name\: $coursename\r\nDescription\: $coursedescription\r\n\r\nIf you have questions regarding this action, please contact {0} {1} ({2}).
diff --git a/src/main/java/org/olat/resource/accesscontrol/Offer.java b/src/main/java/org/olat/resource/accesscontrol/Offer.java
index 8c59b0b518b1ea78a3d40915764830ed9e54d53b..368f67cc4cdb6113ed033a424a9293dd16772682 100644
--- a/src/main/java/org/olat/resource/accesscontrol/Offer.java
+++ b/src/main/java/org/olat/resource/accesscontrol/Offer.java
@@ -68,5 +68,9 @@ public interface Offer extends Persistable {
 	public boolean isAutoBooking();
 	
 	public void setAutoBooking(boolean autoBooking);
+	
+	public boolean isConfirmationEmail();
+
+	public void setConfirmationEmail(boolean confirmationEmail);
 
 }
diff --git a/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java b/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java
index a517ed0173b7f314ef63370b40f63b68eefa950e..d9a3a9e2393b3cc616ac99c95bdf40e84cdaa7d1 100644
--- a/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java
+++ b/src/main/java/org/olat/resource/accesscontrol/manager/ACFrontendManager.java
@@ -41,6 +41,7 @@ import org.olat.core.id.Roles;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.StringHelper;
+import org.olat.core.util.mail.MailPackage;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupService;
 import org.olat.group.manager.BusinessGroupDAO;
@@ -49,6 +50,7 @@ import org.olat.group.model.EnrollState;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryRef;
 import org.olat.repository.RepositoryEntryShort;
+import org.olat.repository.RepositoryMailing;
 import org.olat.repository.RepositoryManager;
 import org.olat.repository.RepositoryService;
 import org.olat.repository.manager.RepositoryEntryRelationDAO;
@@ -113,11 +115,11 @@ public class ACFrontendManager implements ACService {
 	@Autowired
 	private BusinessGroupDAO businessGroupDao;
 	@Autowired
+	private BusinessGroupService businessGroupService;
+	@Autowired
 	private BusinessGroupRelationDAO businessGroupRelationDao;
 	@Autowired
 	private RepositoryEntryRelationDAO repositoryEntryRelationDao;
-	@Autowired
-	private BusinessGroupService businessGroupService;
 
 	/**
 	 * The rule to access the repository entry:<br/>
@@ -479,14 +481,19 @@ public class ACFrontendManager implements ACService {
 		if("BusinessGroup".equals(resourceType)) {
 			BusinessGroup group = businessGroupService.loadBusinessGroup(resource);
 			if(group != null) {
-				EnrollState result = businessGroupService.enroll(identity, null, identity, group, null);
-				return result.isFailed() ? Boolean.FALSE : Boolean.TRUE;
+				MailPackage mailing = new MailPackage(offer.isConfirmationEmail());
+				EnrollState result = businessGroupService.enroll(identity, null, identity, group, mailing);
+				return !result.isFailed();
 			}
 		} else {
-			RepositoryEntryRef entry = repositoryManager.lookupRepositoryEntry(resource, false);
+			RepositoryEntry entry = repositoryManager.lookupRepositoryEntry(resource, false);
 			if(entry != null) {
 				if(!repositoryEntryRelationDao.hasRole(identity, entry, GroupRoles.participant.name())) {
 					repositoryEntryRelationDao.addRole(identity, entry, GroupRoles.participant.name());
+					if(offer.isConfirmationEmail()) {
+						MailPackage mailing = new MailPackage(offer.isConfirmationEmail());
+						RepositoryMailing.sendEmail(identity, identity, entry, RepositoryMailing.Type.addParticipantItself, mailing);
+					}
 				}
 				return true;
 			}
diff --git a/src/main/java/org/olat/resource/accesscontrol/manager/ACOfferDAO.java b/src/main/java/org/olat/resource/accesscontrol/manager/ACOfferDAO.java
index 398013d122564e92ec00f6a1b2f11fe7ac74c60e..53442c6b3cb050b7523ad78f6833ecc86a3bc73c 100644
--- a/src/main/java/org/olat/resource/accesscontrol/manager/ACOfferDAO.java
+++ b/src/main/java/org/olat/resource/accesscontrol/manager/ACOfferDAO.java
@@ -135,6 +135,7 @@ public class ACOfferDAO {
 		offer.setLastModified(now);
 		offer.setResource(resource);
 		offer.setValid(true);
+		offer.setConfirmationEmail(false);
 		if(resourceName != null && resourceName.length() > 255) {
 			resourceName = resourceName.substring(0, 250);
 		}
diff --git a/src/main/java/org/olat/resource/accesscontrol/model/OfferImpl.java b/src/main/java/org/olat/resource/accesscontrol/model/OfferImpl.java
index 5c4f6cb4223d33c17b82bd88aa7e2caad5be54d0..3aa9c4f7183d52ecea65b13f35409c82b14f0bbd 100644
--- a/src/main/java/org/olat/resource/accesscontrol/model/OfferImpl.java
+++ b/src/main/java/org/olat/resource/accesscontrol/model/OfferImpl.java
@@ -98,6 +98,8 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo {
 	private String token;
 	@Column(name="autobooking", nullable=true, insertable=true, updatable=true)
 	private boolean autoBooking;
+	@Column(name="confirmation_email", nullable=true, insertable=true, updatable=true)
+	private boolean confirmationEmail;
 
 	@Column(name="resourceid", nullable=true, insertable=true, updatable=true)
 	private Long resourceId;
@@ -182,6 +184,7 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo {
 		this.validTo = validTo;
 	}
 
+	@Override
 	public Long getResourceId() {
 		return resourceId;
 	}
@@ -190,6 +193,7 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo {
 		this.resourceId = resourceId;
 	}
 
+	@Override
 	public String getResourceTypeName() {
 		return resourceTypeName;
 	}
@@ -198,6 +202,7 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo {
 		this.resourceTypeName = resourceTypeName;
 	}
 
+	@Override
 	public String getResourceDisplayName() {
 		return resourceDisplayName;
 	}
@@ -215,15 +220,25 @@ public class OfferImpl implements Persistable, Offer, ModifiedInfo {
 	public void setDescription(String description) {
 		this.description = description;
 	}
-	
+
+	@Override
 	public boolean isAutoBooking() {
 		return autoBooking;
 	}
-	
+
+	@Override
 	public void setAutoBooking(boolean autoBooking) {
 		this.autoBooking = autoBooking;
 	}
 
+	public boolean isConfirmationEmail() {
+		return confirmationEmail;
+	}
+
+	public void setConfirmationEmail(boolean confirmationEmail) {
+		this.confirmationEmail = confirmationEmail;
+	}
+
 	public String getToken() {
 		return token;
 	}
diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/AbstractConfigurationMethodController.java b/src/main/java/org/olat/resource/accesscontrol/ui/AbstractConfigurationMethodController.java
index 67cc9d65aac158c16646d195abd6c884b152feea..3b9462286db794b5837cb2642eb5335cf8592760 100644
--- a/src/main/java/org/olat/resource/accesscontrol/ui/AbstractConfigurationMethodController.java
+++ b/src/main/java/org/olat/resource/accesscontrol/ui/AbstractConfigurationMethodController.java
@@ -33,10 +33,6 @@ import org.olat.resource.accesscontrol.model.AccessMethod;
 
 /**
  * 
- * Description:<br>
- * TODO: srosse Class Description for AbstractConfigurationMethodController
- * 
- * <P>
  * Initial Date:  18 avr. 2011 <br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  */
@@ -73,6 +69,7 @@ public abstract class AbstractConfigurationMethodController extends FormBasicCon
 	
 	public abstract AccessMethod getMethod();
 
+	@Override
 	public FormItem getInitialFormItem() {
 		return flc;
 	}
diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java b/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java
index 5f30e7fa5e75db21fa9bfb89c99f6bbee46b72dc..e95c3beeb16b3574b7af0c9bd30a7d729c909563 100644
--- a/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java
+++ b/src/main/java/org/olat/resource/accesscontrol/ui/AccessConfigurationController.java
@@ -24,14 +24,13 @@ import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
-import java.util.Map;
 
+import org.olat.core.commons.persistence.DB;
 import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
-import org.olat.core.gui.components.form.flexible.elements.DateChooser;
 import org.olat.core.gui.components.form.flexible.elements.FormLink;
+import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
 import org.olat.core.gui.components.form.flexible.impl.Form;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
 import org.olat.core.gui.components.form.flexible.impl.FormEvent;
@@ -64,8 +63,12 @@ import org.springframework.beans.factory.annotation.Autowired;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  */
 public class AccessConfigurationController extends FormBasicController {
+	
+	private static final String[] onKeys = new String[] { "on" };
 
-	private List<FormLink> addMethods = new ArrayList<FormLink>();
+	private MultipleSelectionElement confirmationEmailEl;
+	private final List<FormLink> addMethods = new ArrayList<>();
+	
 	private final String displayName;
 	private final OLATResource resource;
 
@@ -73,7 +76,7 @@ public class AccessConfigurationController extends FormBasicController {
 	private FormLayoutContainer confControllerContainer;
 	private AbstractConfigurationMethodController newMethodCtrl, editMethodCtrl;
 
-	private final List<AccessInfo> confControllers = new ArrayList<AccessInfo>();
+	private final List<AccessInfo> confControllers = new ArrayList<>();
 
 	private final boolean embbed;
 	private final boolean emptyConfigGrantsFullAccess;
@@ -82,6 +85,8 @@ public class AccessConfigurationController extends FormBasicController {
 
 	private final Formatter formatter;
 
+	@Autowired
+	private DB dbInstance;
 	@Autowired
 	private ACService acService;
 	@Autowired
@@ -144,6 +149,11 @@ public class AccessConfigurationController extends FormBasicController {
 			}
 			((FormLayoutContainer)formLayout).contextPut("methods", addMethods);
 		}
+		
+		String[] onValues = new String[] { "" };
+		confirmationEmailEl = uifactory.addCheckboxesHorizontal("confirmation.email", formLayout, onKeys, onValues);
+		confirmationEmailEl.addActionListener(FormEvent.ONCHANGE);
+		confirmationEmailEl.setVisible(false);
 
 		String confPage = velocity_root + "/configuration_list.html";
 		confControllerContainer = FormLayoutContainer.createCustomFormLayout("conf-controllers", getTranslator(), confPage);
@@ -154,6 +164,15 @@ public class AccessConfigurationController extends FormBasicController {
 
 		confControllerContainer.contextPut("confControllers", confControllers);
 
+		boolean confirmationEmail = false;
+		for(AccessInfo info:confControllers) {
+			Offer offer = info.getLink().getOffer();
+			confirmationEmail |= offer.isConfirmationEmail();
+		}
+		if(confirmationEmail) {
+			confirmationEmailEl.select(onKeys[0], true);
+		}
+
 		if(!embbed) {
 			setFormTitle("accesscontrol.title");
 
@@ -187,16 +206,6 @@ public class AccessConfigurationController extends FormBasicController {
 		//
 	}
 
-	@Override
-	public void event(UserRequest ureq, Component source, Event event) {
-		if(addMethods.contains(source)) {
-			AccessMethod method = (AccessMethod)((Link)source).getUserObject();
-			addMethod(ureq, method);
-		} else {
-			super.event(ureq, source, event);
-		}
-	}
-
 	@Override
 	protected void event(UserRequest ureq, Controller source, Event event) {
 		if(newMethodCtrl == source) {
@@ -243,39 +252,21 @@ public class AccessConfigurationController extends FormBasicController {
 			String cmd = button.getCmd();
 			if("delete".equals(cmd)) {
 				AccessInfo infos = (AccessInfo)source.getUserObject();
-				acService.deleteOffer(infos.getLink().getOffer());
-				confControllers.remove(infos);
+				removeMethod(infos);
 				fireEvent(ureq, Event.CHANGED_EVENT);
 			} else if("edit".equals(cmd)) {
 				AccessInfo infos = (AccessInfo)source.getUserObject();
 				editMethod(ureq, infos);
 			}
+		} else if(confirmationEmailEl == source) {
+			setConfirmationEmail(confirmationEmailEl.isAtLeastSelected(1));
 		}
 		super.formInnerEvent(ureq, source, event);
 	}
 
 	@Override
 	public void formOK(UserRequest ureq) {
-		Map<String,FormItem> formItemMap = confControllerContainer.getFormComponents();
-
-		List<OfferAccess> links = new ArrayList<OfferAccess>();
-		for(AccessInfo info:confControllers) {
-			FormItem dateFrom = formItemMap.get("from_" + info.getLink().getKey());
-			if(dateFrom instanceof DateChooser) {
-				Date from = ((DateChooser)dateFrom).getDate();
-				info.getLink().setValidFrom(from);
-				info.getLink().getOffer().setValidFrom(from);
-			}
-
-			FormItem dateTo = formItemMap.get("to_" + info.getLink().getKey());
-			if(dateTo instanceof DateChooser) {
-				Date to = ((DateChooser)dateTo).getDate();
-				info.getLink().setValidTo(to);
-				info.getLink().getOffer().setValidTo(to);
-			}
-
-			links.add(info.getLink());
-		}
+		//
 	}
 
 	protected void loadConfigurations() {
@@ -320,6 +311,15 @@ public class AccessConfigurationController extends FormBasicController {
 			delLink.setIconLeftCSS("o_icon o_icon-fw o_icon_delete_item");
 			confControllerContainer.add(delLink.getName(), delLink);
 		}
+		
+		updateConfirmationEmail();
+	}
+	
+	private void updateConfirmationEmail() {
+		if(confirmationEmailEl.isVisible() != !confControllers.isEmpty()) {
+			confirmationEmailEl.setVisible(!confControllers.isEmpty());
+			flc.setDirty(true);
+		}
 	}
 
 	private void editMethod(UserRequest ureq, AccessInfo infos) {
@@ -342,7 +342,9 @@ public class AccessConfigurationController extends FormBasicController {
 	}
 
 	protected void addMethod(UserRequest ureq, AccessMethod method) {
+		boolean confirmationEmail = confirmationEmailEl.isVisible() && confirmationEmailEl.isAtLeastSelected(1);
 		Offer offer = acService.createOffer(resource, displayName);
+		offer.setConfirmationEmail(confirmationEmail);
 		OfferAccess link = acService.createOfferAccess(offer, method);
 
 		removeAsListenerAndDispose(newMethodCtrl);
@@ -362,6 +364,23 @@ public class AccessConfigurationController extends FormBasicController {
 			addConfiguration(newLink);
 		}
 	}
+	
+	private void removeMethod(AccessInfo infos) {
+		acService.deleteOffer(infos.getLink().getOffer());
+		confControllers.remove(infos);
+		updateConfirmationEmail();
+	}
+	
+	private void setConfirmationEmail(boolean confirmationEmail) {
+		for(AccessInfo info:confControllers) {
+			Offer offer = info.getLink().getOffer();
+			offer.setConfirmationEmail(confirmationEmail);
+			offer = acService.save(offer);
+		}
+		dbInstance.commit();//make sure all is on the dabatase
+		confControllers.clear();
+		loadConfigurations();
+	}
 
 	public class AccessInfo {
 		private String name;
diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/_content/access_configuration.html b/src/main/java/org/olat/resource/accesscontrol/ui/_content/access_configuration.html
index 0047566062bd6fad59505d6ed0513823ae76a52a..e530afecc3a5027d9e48c322bb1a87186aaa6bae 100644
--- a/src/main/java/org/olat/resource/accesscontrol/ui/_content/access_configuration.html
+++ b/src/main/java/org/olat/resource/accesscontrol/ui/_content/access_configuration.html
@@ -12,6 +12,12 @@
 		#if ($off_info) <div class="o_info">$off_info</div> #end
 	</div></div>
 #end
+	#if($r.visible("confirmation.email"))
+	<div class="form-group">
+		<label class="control-label col-sm-3">$r.translate("confirmation.email")</label>
+		<div class="col-sm-9">$r.render("confirmation.email")</div>
+	</div>
+	#end
 	<div class="form-group">
 		<label class="control-label col-sm-3">$r.translate("ac.methods.label") $r.render("acMethodsLabelHelp")</label>
 		<div class="col-sm-9">$r.render("conf-controllers")</div>
diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_de.properties
index be5ad639800744c5ea0412081a581203497cc5c0..c7a441396c7f8356b0f6c62b076a9f2f370749fd 100644
--- a/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_de.properties
@@ -38,6 +38,7 @@ admin.menu.title.alt=$\:admin.title
 admin.title=Verwaltung der Zugangskontrolle und Buchungsmethoden
 cmd.close=Schliessen
 cmd.title=Zugangskontrolle
+confirmation.email=Best\u00E4tigungsemail f\u00FCr selbst eingetragene Benutzer
 course.closed=$org.olat.course.run\:course.closed
 create=Erstellen
 from=Von\:
diff --git a/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_en.properties
index 701fa5425c9c805a9a16402e168a5b166581a2c7..a47f66b45d118e7e662482cd069e723c093b40f8 100644
--- a/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/resource/accesscontrol/ui/_i18n/LocalStrings_en.properties
@@ -61,6 +61,7 @@ admin.title=Access control and booking methods administration
 
 cmd.close=Close
 cmd.title=Access control
+confirmation.email=Confirmation email for self-registered users
 course.closed=$org.olat.course.run\:course.closed
 create=Create
 from=From\:
diff --git a/src/main/resources/database/mysql/alter_12_3_x_to_12_4_0.sql b/src/main/resources/database/mysql/alter_12_3_x_to_12_4_0.sql
new file mode 100644
index 0000000000000000000000000000000000000000..eed82324d58fb72217f4b71d2637645a8742fdeb
--- /dev/null
+++ b/src/main/resources/database/mysql/alter_12_3_x_to_12_4_0.sql
@@ -0,0 +1,2 @@
+-- access control
+alter table o_ac_offer add column confirmation_email bit default 0;
\ No newline at end of file
diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql
index 1b81da60dffea76270135dc13ec9f305e8135759..79046cbddc5a42f883901f96964d399ea4666565 100644
--- a/src/main/resources/database/mysql/setupDatabase.sql
+++ b/src/main/resources/database/mysql/setupDatabase.sql
@@ -973,6 +973,7 @@ create table  if not exists o_ac_offer (
   resourcetypename varchar(255),
   resourcedisplayname varchar(255),
   autobooking boolean default 0,
+  confirmation_email bit default 0,
   token varchar(255),
   price_amount DECIMAL(12,4),
   price_currency_code VARCHAR(3),
diff --git a/src/main/resources/database/oracle/alter_12_3_x_to_12_4_0.sql b/src/main/resources/database/oracle/alter_12_3_x_to_12_4_0.sql
new file mode 100644
index 0000000000000000000000000000000000000000..d257c2d6adbf503de92a841694dafa9247cfd3d2
--- /dev/null
+++ b/src/main/resources/database/oracle/alter_12_3_x_to_12_4_0.sql
@@ -0,0 +1,2 @@
+-- access control
+alter table o_ac_offer add confirmation_email number default 0;
\ No newline at end of file
diff --git a/src/main/resources/database/oracle/setupDatabase.sql b/src/main/resources/database/oracle/setupDatabase.sql
index 63874e71921ac61afb6e9dff7d6e47e7e1be2fd1..99d5060b4f1c53cd0acd500b02c13f49e25d48ce 100644
--- a/src/main/resources/database/oracle/setupDatabase.sql
+++ b/src/main/resources/database/oracle/setupDatabase.sql
@@ -889,6 +889,7 @@ create table o_ac_offer (
   resourcedisplayname varchar(255 char),
   token varchar(255 char),
   autobooking number default 0 not null,
+  confirmation_email number default 0,
   price_amount number(20,2),
   price_currency_code VARCHAR(3 char),
   offer_desc VARCHAR(2000 char),
diff --git a/src/main/resources/database/postgresql/alter_12_3_x_to_12_4_0.sql b/src/main/resources/database/postgresql/alter_12_3_x_to_12_4_0.sql
new file mode 100644
index 0000000000000000000000000000000000000000..954df84e25a37d0131652627c7938183b06a7c70
--- /dev/null
+++ b/src/main/resources/database/postgresql/alter_12_3_x_to_12_4_0.sql
@@ -0,0 +1,2 @@
+-- access control
+alter table o_ac_offer add column confirmation_email bool default false;
\ No newline at end of file
diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql
index 871f4d4101836e0bd5312c8c46fd7fd7db6ff14a..e1865dc2d22f50a5262c54acda65a5864902e909 100644
--- a/src/main/resources/database/postgresql/setupDatabase.sql
+++ b/src/main/resources/database/postgresql/setupDatabase.sql
@@ -837,6 +837,7 @@ create table o_ac_offer (
   resourcetypename varchar(255),
   resourcedisplayname varchar(255),
   autobooking bool not null default false,
+  confirmation_email bool default false,
   token varchar(255),
   price_amount DECIMAL,
   price_currency_code VARCHAR(3),