diff --git a/src/main/java/org/olat/course/nodes/co/CourseMailTemplate.java b/src/main/java/org/olat/course/nodes/co/CourseMailTemplate.java
index e1bc6a0432ecf8b9849674892d36882febfc7c0c..d13f6f942fae1256e4c28193d4d2a72885191178 100644
--- a/src/main/java/org/olat/course/nodes/co/CourseMailTemplate.java
+++ b/src/main/java/org/olat/course/nodes/co/CourseMailTemplate.java
@@ -22,11 +22,13 @@ package org.olat.course.nodes.co;
 import java.util.Locale;
 
 import org.apache.velocity.VelocityContext;
+import org.olat.basesecurity.BaseSecurity;
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.helpers.Settings;
 import org.olat.core.id.Identity;
 import org.olat.core.id.User;
 import org.olat.core.id.UserConstants;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.mail.MailTemplate;
 import org.olat.repository.RepositoryEntry;
 import org.olat.user.UserManager;
@@ -61,6 +63,7 @@ public class CourseMailTemplate extends MailTemplate {
 		if(sender != null) {
 			User user = sender.getUser();
 			UserManager userManager = CoreSpringFactory.getImpl(UserManager.class);
+			BaseSecurity securityManager = CoreSpringFactory.getImpl(BaseSecurity.class);
 			
 			vContext.put("firstname", user.getProperty(UserConstants.FIRSTNAME, null));
 			vContext.put(UserConstants.FIRSTNAME, user.getProperty(UserConstants.FIRSTNAME, null));
@@ -71,7 +74,11 @@ public class CourseMailTemplate extends MailTemplate {
 			vContext.put("fullName", fullName); 
 			vContext.put("mail", userManager.getUserDisplayEmail(user, locale));
 			vContext.put("email", userManager.getUserDisplayEmail(user, locale));
-			vContext.put("username", sender.getName());
+			String loginName = securityManager.findAuthenticationName(recipient);
+			if(!StringHelper.containsNonWhitespace(loginName)) {
+				loginName = recipient.getName();
+			}
+			vContext.put("username", loginName);
 		}
 	}
 }
diff --git a/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentRunController.java b/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentRunController.java
index 505fabde2785eb3c280cb1fac442c2157d87c430..c29f8a9b18cc62dcc16c2f64882b56110f0831b1 100644
--- a/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentRunController.java
+++ b/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentRunController.java
@@ -803,8 +803,9 @@ public class QTI21AssessmentRunController extends BasicController implements Gen
 		
 		RepositoryEntry courseRe = userCourseEnv.getCourseEnvironment().getCourseGroupManager().getCourseEntry();
 		if (!userCourseEnv.isParticipant() && courseNode instanceof IQTESTCourseNode) {
+			boolean authorMode = !ureq.getUserSession().getRoles().isGuestOnly();
 			displayCtrl = new AssessmentTestDisplayController(ureq, getWindowControl(), new InMemoryOutcomeListener(),
-					testEntry, courseRe, courseNode.getIdent(), deliveryOptions, overrideOptions, true, true, true);
+					testEntry, courseRe, courseNode.getIdent(), deliveryOptions, overrideOptions, true, authorMode, true);
 		} else {
 			displayCtrl = new AssessmentTestDisplayController(ureq, bwControl, this, testEntry, courseRe,
 					courseNode.getIdent(), deliveryOptions, overrideOptions, true, false, false);
diff --git a/src/main/java/org/olat/ims/qti21/manager/archive/QTI21ArchiveFormat.java b/src/main/java/org/olat/ims/qti21/manager/archive/QTI21ArchiveFormat.java
index 5e5c00cd71c66ecd744208b2634796fab1b703e1..c3938204abbba66e3117756687158de65e936654 100644
--- a/src/main/java/org/olat/ims/qti21/manager/archive/QTI21ArchiveFormat.java
+++ b/src/main/java/org/olat/ims/qti21/manager/archive/QTI21ArchiveFormat.java
@@ -500,7 +500,15 @@ public class QTI21ArchiveFormat {
 		Identity assessedIdentity = entry.getIdentity();
 		
 		//user properties
-		if(assessedIdentity == null) {
+		if(anonymizerCallback != null) {
+			String anonymizedName;
+			if(assessedIdentity == null) {
+				anonymizedName = translator.translate("anonym.user");
+			} else {
+				anonymizedName = anonymizerCallback.getAnonymizedUserName(assessedIdentity);
+			}
+			dataRow.addCell(col++, anonymizedName, null);
+		} else if(assessedIdentity == null) {
 			for (UserPropertyHandler userPropertyHandler:userPropertyHandlers) {
 				if (userPropertyHandler != null) {
 					if(userPropertyHandlers.get(0) == userPropertyHandler) {
@@ -510,9 +518,6 @@ public class QTI21ArchiveFormat {
 					}	
 				}	
 			}
-		} else if(anonymizerCallback != null) {
-			String anonymizedName = anonymizerCallback.getAnonymizedUserName(assessedIdentity);
-			dataRow.addCell(col++, anonymizedName, null);
 		} else {
 			User assessedUser = assessedIdentity.getUser();
 			for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) {
diff --git a/src/main/java/org/olat/ims/qti21/resultexport/AssessedMemberComparator.java b/src/main/java/org/olat/ims/qti21/resultexport/AssessedMemberComparator.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f69438af64dd936f66f50f0605784df909a51ca
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/resultexport/AssessedMemberComparator.java
@@ -0,0 +1,61 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.ims.qti21.resultexport;
+
+import java.util.Comparator;
+
+/**
+ * 
+ * Initial date: 28 août 2020<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class AssessedMemberComparator implements Comparator<AssessedMember> {
+
+	@Override
+	public int compare(AssessedMember o1, AssessedMember o2) {
+		int c = 0;
+		
+		String l1 = o1.getLastname();
+		String l2 = o2.getLastname();
+		if(l1 == null || l2 == null) {
+			c = compareNullObjects(l1, l2);
+		} else {
+			c = l1.compareTo(l2);
+		}
+		
+		if(c == 0) {
+			String n1 = o1.getNickname();
+			String n2 = o2.getNickname();
+			if(n1 == null || n2 == null) {
+				c = compareNullObjects(n1, n2);
+			} else {
+				c = n1.compareTo(n2);
+			}
+		}
+		return c;
+	}
+	
+	private final int compareNullObjects(final Object a, final Object b) {
+		boolean ba = (a == null);
+		boolean bb = (b == null);
+		return ba? (bb? 0: -1):(bb? 1: 0);
+	}
+}
diff --git a/src/main/java/org/olat/ims/qti21/resultexport/QTI21ResultsExportMediaResource.java b/src/main/java/org/olat/ims/qti21/resultexport/QTI21ResultsExportMediaResource.java
index 571098bea1a57cc22e9ea99a2917c759ece2a79c..7bd4e0b8a51c9d239498bb6f1ff138dc61098fff 100644
--- a/src/main/java/org/olat/ims/qti21/resultexport/QTI21ResultsExportMediaResource.java
+++ b/src/main/java/org/olat/ims/qti21/resultexport/QTI21ResultsExportMediaResource.java
@@ -86,6 +86,7 @@ import org.olat.ims.qti21.ui.AssessmentResultController;
 import org.olat.modules.assessment.AssessmentEntry;
 import org.olat.repository.RepositoryEntry;
 import org.olat.user.UserManager;
+import org.springframework.beans.factory.annotation.Autowired;
 
 public class QTI21ResultsExportMediaResource implements MediaResource {
 
@@ -108,11 +109,14 @@ public class QTI21ResultsExportMediaResource implements MediaResource {
 	
 	private final Set<RepositoryEntry> testEntries = new HashSet<>();
 	
-	private final UserManager userManager;
-	private final QTI21Service qtiService;
+	@Autowired
+	private UserManager userManager;
+	@Autowired
+	private QTI21Service qtiService;
 	
 	public QTI21ResultsExportMediaResource(CourseEnvironment courseEnv, List<Identity> identities,
-			QTICourseNode courseNode, String archivePath, Locale locale) {	
+			QTICourseNode courseNode, String archivePath, Locale locale) {
+		CoreSpringFactory.autowireObject(this);
 		this.courseNode = courseNode;
 		this.identities = identities;
 		this.courseEnv = courseEnv;
@@ -124,8 +128,6 @@ public class QTI21ResultsExportMediaResource implements MediaResource {
 		ureq.getUserSession().setRoles(Roles.userRoles());
 
 		velocityHelper = VelocityHelper.getInstance();
-		qtiService = CoreSpringFactory.getImpl(QTI21Service.class);
-		userManager = CoreSpringFactory.getImpl(UserManager.class);
 		entry = courseEnv.getCourseGroupManager().getCourseEntry();
 		translator = Util.createPackageTranslator(QTI21ResultsExportMediaResource.class, locale);
 		exportFolderName = ZipUtil.concat(archivePath, translator.translate("export.folder.name"));
@@ -277,13 +279,16 @@ public class QTI21ResultsExportMediaResource implements MediaResource {
 			assessmentEntryMap.put(assessmentEntry.getIdentity(), assessmentEntry);
 		}
 
-		List<AssessedMember> assessedMembers = new ArrayList<>();		
+		List<AssessedMember> assessedMembers = new ArrayList<>();
 		for(Identity identity : identities) {
 			if(identity == null || identity.getStatus() == null || identity.getStatus().equals(Identity.STATUS_DELETED)) {
 				continue;
 			}
-			
-			String lastname = StringHelper.transformDisplayNameToFileSystemName(identity.getUser().getLastName());
+			String lastNameOrAnoymous = identity.getUser().getLastName();
+			if(!StringHelper.containsNonWhitespace(lastNameOrAnoymous)) {
+				lastNameOrAnoymous = "anonym";
+			}
+			String lastname = StringHelper.transformDisplayNameToFileSystemName(lastNameOrAnoymous);
 			String idDir = exportFolderName + "/" + DATA + lastname + "_" + identity.getKey();
 			idDir = idDir.endsWith(SEP) ? idDir : idDir + SEP;
 			createZipDirectory(zout, idDir);				
@@ -303,7 +308,7 @@ public class QTI21ResultsExportMediaResource implements MediaResource {
 			String linkToUser = idDir.replace(exportFolderName + "/", "") + "index.html";
 			String memberEmail = userManager.getUserDisplayEmail(identity, ureq.getLocale());
 			AssessedMember member = new AssessedMember(identity.getUser().getProperty(UserConstants.NICKNAME, null),
-					identity.getUser().getLastName(), identity.getUser().getFirstName(),
+					lastNameOrAnoymous, identity.getUser().getFirstName(),
 					memberEmail, assessments.size(), passed, score, linkToUser);
 			
 			String singleUserInfoHTML = createResultListingHTML(assessments, assessmentDocuments, member);
@@ -373,7 +378,7 @@ public class QTI21ResultsExportMediaResource implements MediaResource {
 	}
 	
 	private String createMemberListingHTML(List<AssessedMember> assessedMembers) {
-		Collections.sort(assessedMembers, (o1, o2) ->  o1.getLastname().compareTo(o2.getLastname()));
+		Collections.sort(assessedMembers, new AssessedMemberComparator());
 		// now put values to velocityContext
 		VelocityContext ctx = new VelocityContext();
 		ctx.put("t", translator);
diff --git a/src/main/java/org/olat/ims/qti21/ui/report/QuestionOriginMediaResource.java b/src/main/java/org/olat/ims/qti21/ui/report/QuestionOriginMediaResource.java
index 0fe31892267a6cd976a0dfa044118f20c184a431..d1b61cbc33ccfdd37716a059e6774e11a0c440bf 100644
--- a/src/main/java/org/olat/ims/qti21/ui/report/QuestionOriginMediaResource.java
+++ b/src/main/java/org/olat/ims/qti21/ui/report/QuestionOriginMediaResource.java
@@ -31,6 +31,10 @@ import org.apache.logging.log4j.Logger;
 import org.olat.basesecurity.GroupRoles;
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.persistence.DB;
+import org.olat.core.commons.services.license.License;
+import org.olat.core.commons.services.license.LicenseModule;
+import org.olat.core.commons.services.license.LicenseService;
+import org.olat.core.commons.services.license.LicenseType;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.Identity;
 import org.olat.core.logging.Tracing;
@@ -47,6 +51,7 @@ import org.olat.ims.qti21.model.xml.ManifestMetadataBuilder;
 import org.olat.imscp.xml.manifest.ResourceType;
 import org.olat.modules.qpool.QPoolService;
 import org.olat.modules.qpool.QuestionItem;
+import org.olat.modules.qpool.manager.QuestionPoolLicenseHandler;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryRelationType;
 import org.olat.repository.RepositoryManager;
@@ -77,6 +82,7 @@ public class QuestionOriginMediaResource extends OpenXMLWorkbookResource {
 	
 	private static final Logger log = Tracing.createLoggerFor(QuestionOriginMediaResource.class);
 	
+	private boolean licenseEnabled;
 	private final Translator translator;
 	private final List<RepositoryEntry> testEntries;
 	private final ConcurrentMap<RepositoryEntry, TestHolder> holdersMap = new ConcurrentHashMap<>();
@@ -88,17 +94,24 @@ public class QuestionOriginMediaResource extends OpenXMLWorkbookResource {
 	@Autowired
 	private QPoolService qpoolService;
 	@Autowired
+	private LicenseService licenseService;
+	@Autowired
 	private ReferenceManager referenceManager;
 	@Autowired
 	private RepositoryManager repositoryManager;
 	@Autowired
 	private RepositoryService repositoryService;
+	@Autowired
+	private LicenseModule licenseModule;
+	@Autowired
+	private QuestionPoolLicenseHandler licenseHandler;
 	
 	public QuestionOriginMediaResource(String label, List<RepositoryEntry> testEntries, Translator translator) {
 		super(label);
 		CoreSpringFactory.autowireObject(this);
 		this.translator = translator;
 		this.testEntries = testEntries;
+		licenseEnabled = licenseModule.isEnabled(licenseHandler);
 	}
 	
 	@Override
@@ -133,11 +146,16 @@ public class QuestionOriginMediaResource extends OpenXMLWorkbookResource {
 		headerRow.addCell(col++, translator.translate("report.question.author"));
 		headerRow.addCell(col++, translator.translate("report.question.identifier"));
 		headerRow.addCell(col++, translator.translate("report.question.keywords"));
+		headerRow.addCell(col++, translator.translate("report.question.taxonomy.level"));
 		headerRow.addCell(col++, translator.translate("report.question.taxonomy.path"));
 		headerRow.addCell(col++, translator.translate("report.question.topic"));
 		headerRow.addCell(col++, translator.translate("report.question.context"));
+		headerRow.addCell(col++, translator.translate("report.question.correction.time"));
 		headerRow.addCell(col++, translator.translate("report.question.type"));
-		
+		if (licenseEnabled) {
+			headerRow.addCell(col++, translator.translate("report.question.license"));
+		}
+
 		// master
 		headerRow.addCell(col++, translator.translate("report.question.master.identifier"));
 		headerRow.addCell(col++, translator.translate("report.question.master.author"));
@@ -190,10 +208,15 @@ public class QuestionOriginMediaResource extends OpenXMLWorkbookResource {
 		row.addCell(col++, question.getAuthor());
 		row.addCell(col++, question.getIdentifier());
 		row.addCell(col++, question.getKeywords());
+		row.addCell(col++, question.getTaxonomyLevel());
 		row.addCell(col++, question.getTaxonomyPath());
 		row.addCell(col++, question.getTopic());
 		row.addCell(col++, question.getEducationalContextLevel());
+		row.addCell(col++, question.getCorrectionTime());
 		row.addCell(col++, question.getType());
+		if(licenseEnabled) {
+			row.addCell(col++, question.getLicense());
+		}
 		
 		// master question
 		row.addCell(col++, question.getMasterIdentifier());
@@ -294,7 +317,8 @@ public class QuestionOriginMediaResource extends OpenXMLWorkbookResource {
 			} else {
 				QuestionItem item = items.get(0);
 				String authors = getAuthors(item);
-				infos = new QuestionInformations(authors, item);
+				String license = getLicense(item);
+				infos = new QuestionInformations(authors, item, license);
 			}
 
 			if(StringHelper.containsNonWhitespace(masterIdentifier)) {
@@ -309,6 +333,28 @@ public class QuestionOriginMediaResource extends OpenXMLWorkbookResource {
 		}
 		return infos;
 	}
+	
+	private String getLicense(QuestionItem item) {
+		License license = null;
+		if(licenseEnabled) {
+			license = licenseService.loadLicense(item);
+		}
+		
+		String licenseText = null;
+		if(license != null) {
+			LicenseType licenseType = license.getLicenseType();
+			if (licenseService.isFreetext(licenseType)) {
+				licenseText = license.getFreetext();
+			} else if (!licenseService.isNoLicense(licenseType)) {
+				licenseText = license.getLicenseType().getName();
+			}
+			
+			if(licenseText != null && licenseText.length() > 32000) {
+				licenseText = licenseText.substring(0, 32000);
+			}
+		}
+		return licenseText;
+	}
 
 	private List<CourseToTestHolder> loadCoursesAndTests() {
 		List<CourseToTestHolder> courseToTestList = new ArrayList<>(128);
@@ -409,31 +455,39 @@ public class QuestionOriginMediaResource extends OpenXMLWorkbookResource {
 		private final String author;
 		private final String keywords;
 		private final String taxonomyPath;
+		private final String taxonomyLevel;
+		private final String correctionTime;
 		private final String topic;
 		private final String context;
 		private final String type;
 		private final String masterIdentifier;
+		private final String license;
 
 		private MasterInformations masterInformations;
 		
-		public QuestionInformations(String author, QuestionItem item) {
+		public QuestionInformations(String author, QuestionItem item, String license) {
 			identifier = item.getIdentifier();
 			title = item.getTitle();
 			this.author = author;
 			keywords = item.getKeywords();
 			taxonomyPath = item.getTaxonomicPath();
+			taxonomyLevel = item.getTaxonomyLevelName();
 			topic = item.getTopic();
 			context = item.getEducationalContextLevel();
 			type = item.getItemType();
 			masterIdentifier = item.getMasterIdentifier();
+			correctionTime = item.getCorrectionTime() == null ? "" : item.getCorrectionTime().toString();
+			this.license = license;
 		}
 		
 		public QuestionInformations(AssessmentItem assessmentItem, ManifestMetadataBuilder metadata, String testOwners) {
 			identifier = metadata.getOpenOLATMetadataIdentifier();
 			if(StringHelper.containsNonWhitespace(metadata.getTitle())) {
 				title = metadata.getTitle();
-			} else {
+			} else if (assessmentItem != null) {
 				title = assessmentItem.getTitle();
+			} else {
+				title = "Unkown";
 			}
 			if(StringHelper.containsNonWhitespace(metadata.getOpenOLATMetadataCreator())) {
 				author = metadata.getOpenOLATMetadataCreator();
@@ -445,6 +499,18 @@ public class QuestionOriginMediaResource extends OpenXMLWorkbookResource {
 
 			keywords = metadata.getGeneralKeywords();
 			taxonomyPath = metadata.getClassificationTaxonomy();
+			
+			String level = null;
+			if(StringHelper.containsNonWhitespace(taxonomyPath)) {
+				int index = taxonomyPath.lastIndexOf('/');
+				if(index >= 0) {
+					level = taxonomyPath.substring(index + 1, taxonomyPath.length());
+				} else {
+					level = taxonomyPath;
+				}
+			}
+			taxonomyLevel = level;
+			
 			topic = metadata.getOpenOLATMetadataTopic();
 			context = metadata.getEducationContext();
 			if(StringHelper.containsNonWhitespace(metadata.getOpenOLATMetadataQuestionType())) {
@@ -453,6 +519,13 @@ public class QuestionOriginMediaResource extends OpenXMLWorkbookResource {
 				type = QTI21QuestionType.getType(assessmentItem).name();
 			}
 			masterIdentifier = metadata.getOpenOLATMetadataMasterIdentifier();
+			correctionTime = metadata.getOpenOLATMetadataCorrectionTime() == null ? "" :  metadata.getOpenOLATMetadataCorrectionTime().toString();
+			
+			String l = metadata.getLicense();
+			if(StringHelper.containsNonWhitespace(l) && l.length() > 32000) {
+				l = l.substring(0, 32000);
+			}
+			license = l;
 		}
 		
 		public QuestionInformations(AssessmentItem assessmentItem) {
@@ -461,16 +534,19 @@ public class QuestionOriginMediaResource extends OpenXMLWorkbookResource {
 			author = null;
 			keywords = null;
 			taxonomyPath = null;
+			taxonomyLevel = null;
 			topic = assessmentItem.getLabel();
 			context = null;
 			masterIdentifier = null;
+			license = null;
 
 			QTI21QuestionType qType = QTI21QuestionType.getType(assessmentItem);
 			if(qType == null) {
 				type = null;
 			} else {
 				type = qType.name();
-			}	
+			}
+			correctionTime = null;
 		}
 
 		public String getAuthor() {
@@ -488,6 +564,10 @@ public class QuestionOriginMediaResource extends OpenXMLWorkbookResource {
 		public String getKeywords() {
 			return keywords;
 		}
+		
+		public String getTaxonomyLevel() {
+			return taxonomyLevel;
+		}
 
 		public String getTaxonomyPath() {
 			return taxonomyPath;
@@ -500,6 +580,14 @@ public class QuestionOriginMediaResource extends OpenXMLWorkbookResource {
 		public String getEducationalContextLevel() {
 			return context;
 		}
+		
+		public String getCorrectionTime() {
+			return correctionTime;
+		}
+		
+		public String getLicense() {
+			return license;
+		}
 
 		public String getType() {
 			return type;
diff --git a/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_de.properties
index d0bf6ef456a54e04dc18e44ffe3209d16c3ccf9b..96b9b6721dddf5784ad5f38f80afc8c0ad1acfad 100644
--- a/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_de.properties
@@ -7,8 +7,11 @@ report.course.id=Kurs ID
 report.explain=Report: gew\u00E4hlte Tests inklusive aller enthaltenen Fragen
 report.question.title=Titel der Frage
 report.question.author=Ersteller der Frage (Besitzer)
+report.question.correction.time=$org.olat.modules.qpool.ui\:question.correctionTime
 report.question.identifier=Frage ID
 report.question.keywords=Schlagwort
+report.question.license=$org.olat.modules.qpool.ui\:rights.license
+report.question.taxonomy.level=Fachbereich
 report.question.taxonomy.path=Fachbereichpfad
 report.question.topic=Thema
 report.question.context=Stufe
diff --git a/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_en.properties
index d94fb26cbc8944532d68bb42c9524128c64e4bb4..43dabce57308d76405c1198f6c706aedbdaf20f3 100644
--- a/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_en.properties
@@ -7,8 +7,11 @@ report.course.id=Course ID
 report.explain=Report: selected tests including all contained questions
 report.question.title=Question's title
 report.question.author=Question's creator (owner)
+report.question.correction.time=$org.olat.modules.qpool.ui\:question.correctionTime
 report.question.identifier=Question ID
 report.question.keywords=Keywords
+report.question.license=$org.olat.modules.qpool.ui\:rights.license
+report.question.taxonomy.level=Subject
 report.question.taxonomy.path=Subject path
 report.question.topic=Topic
 report.question.context=Level
diff --git a/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_fr.properties
index 880a23dec8365f142992d3fd9f8654d76356a2dd..04f180d60f5824bf1b1b7a1f62c8aedd44abb507 100644
--- a/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/report/_i18n/LocalStrings_fr.properties
@@ -7,11 +7,14 @@ report.course.id=ID du cours
 report.explain=Rapport\: les tests s\u00E9lectionn\u00E9s et toutes leurs questions
 report.question.author=Cr\u00E9ateur de la question (propri\u00E9taire)
 report.question.context=Niveau
+report.question.correction.time=$org.olat.modules.qpool.ui\:question.correctionTime
 report.question.identifier=Question ID
 report.question.keywords=Mots cl\u00E9s
+report.question.license=$org.olat.modules.qpool.ui\:rights.license
 report.question.master.author=Cr\u00E9ateur (propri\u00E9taire master ID)
 report.question.master.identifier=Question master ID
 report.question.master.keywords=Mots cl\u00E9s (question master ID)
+report.question.taxonomy.level=Sujet
 report.question.taxonomy.path=Sujet chemin
 report.question.title=Titre de la question
 report.question.to.course=Rapport questions
diff --git a/src/main/java/org/olat/modules/reminder/manager/ReminderServiceImpl.java b/src/main/java/org/olat/modules/reminder/manager/ReminderServiceImpl.java
index fd97b219c23205d468fff84b5c8e2e653fcec6af..2616bd58ccf0c5d1adc3eeac897f62d14651dd3a 100644
--- a/src/main/java/org/olat/modules/reminder/manager/ReminderServiceImpl.java
+++ b/src/main/java/org/olat/modules/reminder/manager/ReminderServiceImpl.java
@@ -32,6 +32,7 @@ import java.util.UUID;
 
 import org.apache.logging.log4j.Logger;
 import org.apache.velocity.VelocityContext;
+import org.olat.basesecurity.BaseSecurity;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.helpers.Settings;
 import org.olat.core.id.Identity;
@@ -87,6 +88,8 @@ public class ReminderServiceImpl implements ReminderService {
 	private UserManager userManager;
 	@Autowired
 	private ReminderRuleEngine ruleEngine;
+	@Autowired
+	private BaseSecurity securityManager;
 	
 	@Override
 	public Reminder createReminder(RepositoryEntry entry, Identity creator) {
@@ -284,16 +287,21 @@ public class ReminderServiceImpl implements ReminderService {
 		@Override
 		public void putVariablesInMailContext(VelocityContext vContext, Identity recipient) {
 			User user = recipient.getUser();
-			vContext.put("firstname", user.getProperty(UserConstants.FIRSTNAME, null));
-			vContext.put(UserConstants.FIRSTNAME, user.getProperty(UserConstants.FIRSTNAME, null));
-			vContext.put("lastname", user.getProperty(UserConstants.LASTNAME, null));
-			vContext.put(UserConstants.LASTNAME, user.getProperty(UserConstants.LASTNAME, null));
+			vContext.put("firstname", user.getFirstName());
+			vContext.put(UserConstants.FIRSTNAME, user.getFirstName());
+			vContext.put("lastname", user.getLastName());
+			vContext.put(UserConstants.LASTNAME, user.getLastName());
 			String fullName = userManager.getUserDisplayName(recipient);
 			vContext.put("fullname", fullName);
 			vContext.put("fullName", fullName); 
-			vContext.put("mail", userManager.getUserDisplayEmail(user, locale));
-			vContext.put("email", userManager.getUserDisplayEmail(user, locale));
-			vContext.put("username", recipient.getName());
+			String email = userManager.getUserDisplayEmail(user, locale);
+			vContext.put("mail", email);
+			vContext.put("email", email);
+			String loginName = securityManager.findAuthenticationName(recipient);
+			if(!StringHelper.containsNonWhitespace(loginName)) {
+				loginName = recipient.getName();
+			}
+			vContext.put("username", loginName);
 			// Put variables from greater context
 			if(entry != null) {
 				vContext.put("courseurl", url);
diff --git a/src/main/java/org/olat/user/manager/lifecycle/UserLifecycleManagerImpl.java b/src/main/java/org/olat/user/manager/lifecycle/UserLifecycleManagerImpl.java
index 59f35b3db4101177308b27721281b29b75ead7fb..765e70c0c607e3eb0f2a822b57bce830482dac91 100644
--- a/src/main/java/org/olat/user/manager/lifecycle/UserLifecycleManagerImpl.java
+++ b/src/main/java/org/olat/user/manager/lifecycle/UserLifecycleManagerImpl.java
@@ -45,8 +45,10 @@ import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.Identity;
+import org.olat.core.id.User;
 import org.olat.core.id.UserConstants;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.Util;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.mail.MailBundle;
@@ -57,6 +59,7 @@ import org.olat.core.util.session.UserSessionManager;
 import org.olat.repository.RepositoryDeletionModule;
 import org.olat.user.UserDataDeletable;
 import org.olat.user.UserLifecycleManager;
+import org.olat.user.UserManager;
 import org.olat.user.UserModule;
 import org.olat.user.ui.admin.lifecycle.UserAdminLifecycleConfigurationController;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -84,6 +87,8 @@ public class UserLifecycleManagerImpl implements UserLifecycleManager {
 	@Autowired
 	private MailManager mailManager;
 	@Autowired
+	private UserManager userManager;
+	@Autowired
 	private BaseSecurity securityManager;
 	@Autowired
 	private UserSessionManager userSessionManager;
@@ -331,7 +336,7 @@ public class UserLifecycleManagerImpl implements UserLifecycleManager {
 		
 		String subject = translator.translate(subjectI18nKey);
 		String body = translator.translate(bodyI18nKey);
-		LifecycleMailTemplate template = new LifecycleMailTemplate(subject, body);
+		LifecycleMailTemplate template = new LifecycleMailTemplate(subject, body, locale);
 		
 		sendUserEmailTo(identity, template, type);
 	}
@@ -356,15 +361,35 @@ public class UserLifecycleManagerImpl implements UserLifecycleManager {
 		return CalendarUtils.startOfDay(date);
 	}
 	
-	private static final class LifecycleMailTemplate extends MailTemplate {
+	private final class LifecycleMailTemplate extends MailTemplate {
+		
+		private final Locale locale;
 		
-		public LifecycleMailTemplate(String subject, String body) {
+		public LifecycleMailTemplate(String subject, String body, Locale locale) {
 			super(subject, body, null);
+			this.locale = locale;
 		}
 
 		@Override
 		public void putVariablesInMailContext(VelocityContext vContext, Identity recipient) {
-			//
+			if(recipient != null) {
+				User user = recipient.getUser();
+				
+				vContext.put("firstname", user.getProperty(UserConstants.FIRSTNAME, null));
+				vContext.put(UserConstants.FIRSTNAME, user.getProperty(UserConstants.FIRSTNAME, null));
+				vContext.put("lastname", user.getProperty(UserConstants.LASTNAME, null));
+				vContext.put(UserConstants.LASTNAME, user.getProperty(UserConstants.LASTNAME, null));
+				String fullName = userManager.getUserDisplayName(recipient);
+				vContext.put("fullname", fullName);
+				vContext.put("fullName", fullName); 
+				vContext.put("mail", userManager.getUserDisplayEmail(user, locale));
+				vContext.put("email", userManager.getUserDisplayEmail(user, locale));
+				String loginName = securityManager.findAuthenticationName(recipient);
+				if(!StringHelper.containsNonWhitespace(loginName)) {
+					loginName = recipient.getName();
+				}
+				vContext.put("username", loginName);
+			}
 		}
 	}