示例#1
0
        private void buttonAdd_Click(object sender, EventArgs e)
        {
            formInputDialog inputDialog = new formInputDialog();

            inputDialog.Title = "Alias name";
            inputDialog.Text  = "Enter domain alias name";

            if (inputDialog.ShowDialog() == DialogResult.OK)
            {
                // Add it
                string value = inputDialog.Value;

                hMailServer.DomainAliases domainAliases = _domain.DomainAliases;

                DomainAlias domainAlias = domainAliases.Add();
                domainAlias.AliasName = value;
                try
                {
                    domainAlias.Save();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, EnumStrings.hMailServerAdministrator);
                    return;
                }

                Marshal.ReleaseComObject(domainAliases);
                Marshal.ReleaseComObject(domainAlias);

                ListDomainAliases();
            }
        }
示例#2
0
        public override List <DomainAlias> GetDomainAliases(string domainName)
        {
            var _tmp = new List <DomainAlias>();

            using (OleDbConnection _conn = new OleDbConnection(connectionString))
            {
                _conn.Open();
                using (OleDbCommand _cmd = new OleDbCommand(@"SELECT Host_Accounts.Domain_Name, Alias_Details.Alias_Domainname
                                                                        FROM (Host_Accounts INNER JOIN
                                                                                  Alias_Details ON Host_Accounts.Host_ID = Alias_Details.Host_ID)
                                                                    WHERE (Host_Accounts.Domain_Name = ?)", _conn))
                {
                    _cmd.CommandType = CommandType.Text;
                    _cmd.Parameters.AddWithValue("NAME", domainName);

                    using (OleDbDataReader _read = _cmd.ExecuteReader())
                    {
                        while (_read.Read())
                        {
                            var _d = new DomainAlias();
                            _d.Domain = _read["Domain_Name"].ToString();
                            _d.Alias  = _read["Alias_Domainname"].ToString();

                            _tmp.Add(_d);
                        }
                    }
                }
                _conn.Close();
            }

            return(_tmp);
        }
示例#3
0
        public void TestDistributionListAnnouncementFromDomainAlias()
        {
            var smtpClientSimulator = new SmtpClientSimulator();

            //
            // TEST LIST SECURITY IN COMBINATION WITH DOMAIN NAME ALIASES
            //


            Account account = SingletonProvider <TestSetup> .Instance.AddAccount(_domain, "*****@*****.**", "test");

            var recipients = new List <string>();

            recipients.Add("*****@*****.**");

            DistributionList list3 = SingletonProvider <TestSetup> .Instance.AddDistributionList(_domain, "*****@*****.**",
                                                                                                 recipients);

            list3.Mode = eDistributionListMode.eLMAnnouncement;
            list3.RequireSenderAddress = "*****@*****.**";
            list3.Save();

            // THIS MESSAGE SHOULD FAIL
            CustomAsserts.Throws <DeliveryFailedException>(() => smtpClientSimulator.Send("*****@*****.**", "*****@*****.**", "Mail 1", "Mail 1"));

            DomainAlias domainAlias = _domain.DomainAliases.Add();

            domainAlias.AliasName = "dummy-example.com";
            domainAlias.Save();

            // THIS MESSAGE SHOULD SUCCEED
            smtpClientSimulator.Send("*****@*****.**", "*****@*****.**", "Mail 1", "Mail 1");
            ImapClientSimulator.AssertMessageCount("*****@*****.**", "test", "Inbox", 1);
        }
示例#4
0
        public override List <DomainAlias> GetDomainAliases(string domainName)
        {
            var _tmp = new List <DomainAlias>();

            using (OleDbConnection _conn = new OleDbConnection(connectionString))
            {
                _conn.Open();
                using (OleDbCommand _cmd = new OleDbCommand(@"SELECT domain_aliases.name AS alias, domains.name AS [domain], domain_aliases.status
                                                                FROM (domain_aliases INNER JOIN
                                                            domains ON domain_aliases.dom_id = domains.id)
                                                                WHERE (domain_aliases.status = 0) AND (domains.name = ?)", _conn))
                {
                    _cmd.CommandType = CommandType.Text;
                    _cmd.Parameters.AddWithValue("NAME", domainName);

                    using (OleDbDataReader _read = _cmd.ExecuteReader())
                    {
                        while (_read.Read())
                        {
                            var _d = new DomainAlias();
                            _d.Domain = _read["domain"].ToString();
                            _d.Alias  = _read["alias"].ToString();

                            _tmp.Add(_d);
                        }
                    }
                }
                _conn.Close();
            }

            return(_tmp);
        }
示例#5
0
        public override List <DomainAlias> GetDomainAliases(string domainName)
        {
            var _tmp = new List <DomainAlias>();

            using (SQLiteConnection _conn = new SQLiteConnection(connectionString))
            {
                _conn.Open();

                using (SQLiteCommand _cmd = new SQLiteCommand(@"SELECT DomainAlias.Hostname FROM Domain 
                                                            INNER JOIN  DomainAlias ON Domain.DomainId = DomainAlias.DomainId  WHERE (Domain.Name = @NAME)", _conn))
                {
                    _cmd.Parameters.AddWithValue("@NAME", domainName);

                    using (SQLiteDataReader _read = _cmd.ExecuteReader())
                    {
                        while (_read.Read())
                        {
                            var da = new DomainAlias();
                            da.Alias  = DataExtensions.GetColumnValue <String>(_read, "Hostname");
                            da.Domain = domainName;
                            da.Status = 1;

                            _tmp.Add(da);
                        }
                    }
                }

                _conn.Close();
            }

            return(_tmp);
        }
示例#6
0
        public override List <DomainAlias> GetDomainAliases(string domainName)
        {
            var _tmp = new List <DomainAlias>();

            using (SqlConnection _conn = new SqlConnection(connectionString))
            {
                _conn.Open();
                using (SqlCommand _cmd = new SqlCommand(@"SELECT D.Name as domain, DA.Hostname as name FROM DomainAlias As DA 
                                                                LEFT JOIN Domain As D ON D.DomainId = Da.DomainId WHERE D.Name = @NAME", _conn))
                {
                    _cmd.Parameters.AddWithValue("@NAME", domainName);

                    using (SqlDataReader _read = _cmd.ExecuteReader())
                    {
                        while (_read.Read())
                        {
                            var _d = new DomainAlias();
                            _d.Domain = _read["domain"].ToString();
                            _d.Alias  = _read["name"].ToString();

                            _tmp.Add(_d);
                        }
                    }
                }
                _conn.Close();
            }

            return(_tmp);
        }
示例#7
0
        public override List <DomainAlias> GetDomainAliases(string domainName)
        {
            var _tmp = new List <DomainAlias>();

            using (MySqlConnection _conn = new MySqlConnection(connectionString))
            {
                _conn.Open();
                using (MySqlCommand _cmd = new MySqlCommand(@"SELECT domain_aliases.name as alias, domains.name AS domain, domain_aliases.status
                                                                FROM  domain_aliases 
                                                            INNER JOIN domains ON domain_aliases.dom_id = domains.id
                                                            WHERE domain_aliases.status = 0 AND domains.name = @NAME", _conn))
                {
                    _cmd.Parameters.AddWithValue("@NAME", domainName);

                    using (MySqlDataReader _read = _cmd.ExecuteReader())
                    {
                        while (_read.Read())
                        {
                            var _d = new DomainAlias();
                            _d.Domain = DataExtensions.GetColumnValue <String>(_read, "domain");
                            _d.Alias  = DataExtensions.GetColumnValue <String>(_read, "alias");
                            //_d.Status = DataExtensions.GetColumnValue<long>(_read, "status");

                            _tmp.Add(_d);
                        }
                    }
                }
                _conn.Close();
            }

            return(_tmp);
        }
示例#8
0
        /// <summary>
        /// Inserts a Domain alias of the customer.
        /// Documentation https://developers.google.com/directory/directory_v1/reference/domainAliases/insert
        /// Generation Note: This does not always build corectly.  Google needs to standardise things I need to figuer out which ones are wrong.
        /// </summary>
        /// <param name="service">Authenticated Directory service.</param>
        /// <param name="customer">Immutable ID of the G Suite account.</param>
        /// <param name="body">A valid Directory directory_v1 body.</param>
        /// <returns>DomainAliasResponse</returns>
        public static DomainAlias Insert(DirectoryService service, string customer, DomainAlias body)
        {
            try
            {
                // Initial validation.
                if (service == null)
                {
                    throw new ArgumentNullException("service");
                }
                if (body == null)
                {
                    throw new ArgumentNullException("body");
                }
                if (customer == null)
                {
                    throw new ArgumentNullException(customer);
                }

                // Make the request.
                return(service.DomainAliases.Insert(body, customer).Execute());
            }
            catch (Exception ex)
            {
                throw new Exception("Request DomainAliases.Insert failed.", ex);
            }
        }
示例#9
0
        public override List <DomainAlias> GetDomainAliases(string domainName)
        {
            var _tmp = new List <DomainAlias>();

            using (OleDbConnection _conn = new OleDbConnection(connectionString))
            {
                _conn.Open();
                using (OleDbCommand _cmd = new OleDbCommand(@"SELECT domain_aliases.name AS alias, domains.name AS [domain], domain_aliases.status
                                                                    FROM (domain_aliases INNER JOIN
                                                                                             domains ON domain_aliases.dom_id = domains.id)
                                                                    WHERE        (domains.name = ?) AND (domain_aliases.status = 0)", _conn))
                {
                    _cmd.Parameters.AddWithValue("@NAME", domainName);

                    using (OleDbDataReader _read = _cmd.ExecuteReader())
                    {
                        while (_read.Read())
                        {
                            var _d = new DomainAlias();
                            _d.Domain = DataExtensions.GetColumnValue <String>(_read, "domain");
                            _d.Alias  = DataExtensions.GetColumnValue <String>(_read, "alias");
                            _d.Status = Convert.ToInt64(DataExtensions.GetColumnValue <decimal>(_read, "status"));

                            _tmp.Add(_d);
                        }
                    }
                }
                _conn.Close();
            }

            return(_tmp);
        }
示例#10
0
        public void TestDistributionListsMembershipDomainAliases()
        {
            var imap = new ImapClientSimulator();
            var smtpClientSimulator = new SmtpClientSimulator();

            Application application = SingletonProvider <TestSetup> .Instance.GetApp();


            DomainAlias domainAlias = _domain.DomainAliases.Add();

            domainAlias.AliasName = "dummy-example.com";
            domainAlias.Save();

            Account account = SingletonProvider <TestSetup> .Instance.AddAccount(_domain, "*****@*****.**", "test");

            account = SingletonProvider <TestSetup> .Instance.AddAccount(_domain, "*****@*****.**", "test");


            //
            // TEST LIST SECURITY IN COMBINATION WITH DOMAIN NAME ALIASES
            //


            var recipients = new List <string>();

            recipients.Clear();
            recipients.Add("*****@*****.**");

            DistributionList list3 = SingletonProvider <TestSetup> .Instance.AddDistributionList(_domain, "*****@*****.**",
                                                                                                 recipients);

            list3.Mode = eDistributionListMode.eLMMembership;
            list3.Save();

            // THIS MESSAGE SHOULD FAIL - Membership required, unknown sender domain
            CustomAsserts.Throws <DeliveryFailedException>(() => smtpClientSimulator.Send("*****@*****.**", "*****@*****.**", "Mail 1", "Mail 1"));

            list3.Delete();

            // THIS MESSAGE SHOULD SUCCED - Membership required, sender domain is now an alias for test.com.

            recipients = new List <string>();
            recipients.Clear();
            recipients.Add("*****@*****.**");
            recipients.Add("*****@*****.**");

            list3 = SingletonProvider <TestSetup> .Instance.AddDistributionList(_domain, "*****@*****.**", recipients);

            list3.Mode = eDistributionListMode.eLMMembership;
            list3.Save();

            smtpClientSimulator.Send("*****@*****.**", "*****@*****.**", "Mail 1", "Mail 1");

            ImapClientSimulator.AssertMessageCount("*****@*****.**", "test", "Inbox", 1);
            ImapClientSimulator.AssertMessageCount("*****@*****.**", "test", "Inbox", 1);
        }
        public void TestDistributionListsMembershipDomainAliases()
        {
            var oIMAP = new IMAPClientSimulator();
            var oSMTP = new SMTPClientSimulator();

            Application application = SingletonProvider <TestSetup> .Instance.GetApp();


            DomainAlias oDA = _domain.DomainAliases.Add();

            oDA.AliasName = "dummy-example.com";
            oDA.Save();

            Account oAccount = SingletonProvider <TestSetup> .Instance.AddAccount(_domain, "*****@*****.**", "test");

            oAccount = SingletonProvider <TestSetup> .Instance.AddAccount(_domain, "*****@*****.**", "test");


            //
            // TEST LIST SECURITY IN COMBINATION WITH DOMAIN NAME ALIASES
            //


            var oRecipients = new List <string>();

            oRecipients.Clear();
            oRecipients.Add("*****@*****.**");

            DistributionList oList3 = SingletonProvider <TestSetup> .Instance.AddDistributionList(_domain, "*****@*****.**",
                                                                                                  oRecipients);

            oList3.Mode = eDistributionListMode.eLMMembership;
            oList3.Save();

            // THIS MESSAGE SHOULD FAIL - Membership required, unknown sender domain
            CustomAssert.IsFalse(oSMTP.Send("*****@*****.**", "*****@*****.**", "Mail 1", "Mail 1"));

            oList3.Delete();

            // THIS MESSAGE SHOULD SUCCED - Membership required, sender domain is now an alias for test.com.

            oRecipients = new List <string>();
            oRecipients.Clear();
            oRecipients.Add("*****@*****.**");
            oRecipients.Add("*****@*****.**");

            oList3 = SingletonProvider <TestSetup> .Instance.AddDistributionList(_domain, "*****@*****.**", oRecipients);

            oList3.Mode = eDistributionListMode.eLMMembership;
            oList3.Save();

            CustomAssert.IsTrue(oSMTP.Send("*****@*****.**", "*****@*****.**", "Mail 1", "Mail 1"));

            IMAPClientSimulator.AssertMessageCount("*****@*****.**", "test", "Inbox", 1);
            IMAPClientSimulator.AssertMessageCount("*****@*****.**", "test", "Inbox", 1);
        }
示例#12
0
        public void TestSendToPostmasterAddressDomainAlias()
        {
            DomainAlias alias = _domain.DomainAliases.Add();

            alias.AliasName = "alias.com";
            alias.Save();

            _domain.Postmaster = "*****@*****.**";
            _domain.Save();

            Account account = SingletonProvider <TestSetup> .Instance.AddAccount(_domain, "*****@*****.**", "test");

            SmtpClientSimulator.StaticSend("*****@*****.**", "*****@*****.**", "Test", "Test");

            Pop3ClientSimulator.AssertMessageCount(account.Address, "test", 1);
        }
示例#13
0
        public void DomainAliasesShouldNotRewriteRecipientList()
        {
            DomainAlias oDA = _domain.DomainAliases.Add();

            oDA.AliasName = "dummy-example.com";
            oDA.Save();

            Account account = SingletonProvider <TestSetup> .Instance.AddAccount(_domain, "*****@*****.**", "test");

            // Set up a server listening on port 250 which accepts email for [email protected]
            var deliveryResults = new Dictionary <string, int>();

            deliveryResults["*****@*****.**"] = 250;

            int smtpServerPort = TestSetup.GetNextFreePort();

            using (var server = new SmtpServerSimulator(1, smtpServerPort))
            {
                server.AddRecipientResult(deliveryResults);
                server.StartListen();


                Route route = TestSetup.AddRoutePointingAtLocalhost(1, smtpServerPort, true, eConnectionSecurity.eCSNone);

                // Now send a message from [email protected] to [email protected].
                // Error scenario:
                // In the recipientlist, otherdomain.com gets rewritten to test.com
                // since there's a domain alias named otherdomain.co on the domain
                // test.com.
                //
                // This should not happen. Otherdomain.com is an alias for test.com,
                // but we shouldn't actually modify the recipient address just because
                // of this.
                var smtpClient = new SmtpClientSimulator();
                smtpClient.Send(account.Address, "*****@*****.**", "Test", "Test message");

                CustomAsserts.AssertRecipientsInDeliveryQueue(0);

                Pop3ClientSimulator.AssertMessageCount(account.Address, "test", 0);

                // This should now be processed via the rule -> route -> external server we've set up.
                server.WaitForCompletion();

                Assert.IsTrue(server.MessageData.Contains("Test message"));
            }
        }
示例#14
0
        public void TestGreyListingWithDomainAliases()
        {
            _antiSpam.GreyListingEnabled = false;

            Account oAccount1 = SingletonProvider <TestSetup> .Instance.AddAccount(_domain, "*****@*****.**", "test");

            var smtp       = new SMTPClientSimulator();
            var recipients = new List <string>();

            recipients.Add(oAccount1.Address);
            bool result = smtp.Send("*****@*****.**", recipients, "Test", "Body");

            CustomAssert.IsTrue(result);
            POP3ClientSimulator.AssertGetFirstMessageText(oAccount1.Address, "test");

            _antiSpam.GreyListingEnabled = true;

            result = smtp.Send("*****@*****.**", recipients, "Test", "Body");
            CustomAssert.IsFalse(result);

            _domain.AntiSpamEnableGreylisting = false;
            _domain.Save();

            result = smtp.Send("*****@*****.**", recipients, "Test", "Body");
            CustomAssert.IsTrue(result);
            POP3ClientSimulator.AssertGetFirstMessageText(oAccount1.Address, "test");

            DomainAlias da = _domain.DomainAliases.Add();

            da.AliasName = "test2.com";
            da.Save();

            recipients = new List <string>();
            recipients.Add("*****@*****.**");

            result = smtp.Send("*****@*****.**", recipients, "Test", "Body");
            CustomAssert.IsTrue(result);
            POP3ClientSimulator.AssertGetFirstMessageText(oAccount1.Address, "test");

            _domain.AntiSpamEnableGreylisting = true;
            _domain.Save();

            result = smtp.Send("*****@*****.**", recipients, "Test", "Body");
            CustomAssert.IsFalse(result);
        }
示例#15
0
        public void TestDomainAliasWithSameNameAsDomain()
        {
            Domains domains = SingletonProvider <TestSetup> .Instance.GetApp().Domains;

            DomainAlias da = _domain.DomainAliases.Add();

            da.AliasName = "test.com";

            try
            {
                da.Save();
            }
            catch (Exception)
            {
                return;
            }
            Assert.Fail("Domain alias with same name as domain was permitted.");
        }
示例#16
0
        private void ListDomainAliases()
        {
            listAliases.Items.Clear();

            DomainAliases domainAliases = _domain.DomainAliases;

            for (int i = 0; i < domainAliases.Count; i++)
            {
                DomainAlias domainAlias = domainAliases[i];

                ListViewItem item = listAliases.Items.Add(domainAlias.AliasName);
                item.Tag = domainAlias.ID;

                Marshal.ReleaseComObject(domainAlias);
            }

            Marshal.ReleaseComObject(domainAliases);
        }
示例#17
0
        public void TestGreyListingWithDomainAliases()
        {
            _antiSpam.GreyListingEnabled = false;

            Account account1 = SingletonProvider <TestSetup> .Instance.AddAccount(_domain, "*****@*****.**", "test");

            var smtp       = new SmtpClientSimulator();
            var recipients = new List <string>();

            recipients.Add(account1.Address);
            smtp.Send("*****@*****.**", recipients, "Test", "Body");

            Pop3ClientSimulator.AssertGetFirstMessageText(account1.Address, "test");

            _antiSpam.GreyListingEnabled = true;

            CustomAsserts.Throws <DeliveryFailedException>(() => smtp.Send("*****@*****.**", recipients, "Test", "Body"));


            _domain.AntiSpamEnableGreylisting = false;
            _domain.Save();

            smtp.Send("*****@*****.**", recipients, "Test", "Body");

            Pop3ClientSimulator.AssertGetFirstMessageText(account1.Address, "test");

            DomainAlias da = _domain.DomainAliases.Add();

            da.AliasName = "test2.com";
            da.Save();

            recipients = new List <string>();
            recipients.Add("*****@*****.**");

            smtp.Send("*****@*****.**", recipients, "Test", "Body");
            Pop3ClientSimulator.AssertGetFirstMessageText(account1.Address, "test");

            _domain.AntiSpamEnableGreylisting = true;
            _domain.Save();

            CustomAsserts.Throws <DeliveryFailedException>(() => smtp.Send("*****@*****.**", recipients, "Test", "Body"));
        }
示例#18
0
        public void TestPostmasterOnSecondDomainWithDomainAlias()
        {
            Domain otherDomain =
                SingletonProvider <TestSetup> .Instance.AddDomain(SingletonProvider <TestSetup> .Instance.GetApp().Domains,
                                                                  "otherDomain.com");

            DomainAlias otherDomainAlias = otherDomain.DomainAliases.Add();

            otherDomainAlias.AliasName = "name2.com";
            otherDomainAlias.Save();

            _domain.Postmaster = "*****@*****.**";
            _domain.Save();

            Account account = SingletonProvider <TestSetup> .Instance.AddAccount(otherDomain, "*****@*****.**",
                                                                                 "test");

            SmtpClientSimulator.StaticSend("*****@*****.**", "*****@*****.**", "Test", "Test");

            Pop3ClientSimulator.AssertMessageCount(account.Address, "test", 1);
        }
示例#19
0
        private void SetupDomainObject(Domain domain)
        {
            domain.Postmaster               = "*****@*****.**";
            domain.SignatureEnabled         = true;
            domain.AddSignaturesToLocalMail = true;
            domain.AddSignaturesToReplies   = true;

            domain.SignaturePlainText = "PLS";
            domain.SignatureHTML      = "HTML";
            domain.Save();

            DomainAlias da = domain.DomainAliases.Add();

            da.AliasName = "test1.com";
            da.Save();

            DomainAlias da2 = domain.DomainAliases.Add();

            da2.AliasName = "test2.com";
            da2.Save();
        }
示例#20
0
        public void TestDomainAliases()
        {
            // Create a test account
            // Fetch the default domain
            DomainAlias oDomainAlias = _domain.DomainAliases.Add();

            oDomainAlias.AliasName = "alias.com";
            oDomainAlias.Save();

            Account account = SingletonProvider <TestSetup> .Instance.AddAccount(_domain, "*****@*****.**",
                                                                                 "test");

            // Send 5 messages to this account.
            var smtpClientSimulator = new SmtpClientSimulator();

            for (int i = 0; i < 5; i++)
            {
                smtpClientSimulator.Send("*****@*****.**", "*****@*****.**", "INBOX", "Alias test message");
            }

            Pop3ClientSimulator.AssertMessageCount("*****@*****.**", "test", 5);

            {
                account = SingletonProvider <TestSetup> .Instance.AddAccount(_domain,
                                                                             "*****@*****.**", "test");

                // Set up an alias pointing at the domain alias.
                SingletonProvider <TestSetup> .Instance.AddAlias(_domain, "*****@*****.**",
                                                                 "*****@*****.**");

                // Send to the alias
                for (int i = 0; i < 5; i++)
                {
                    smtpClientSimulator.Send(account.Address, "*****@*****.**", "INBOX", "Plus addressing message");
                }
                // Wait for completion

                Pop3ClientSimulator.AssertMessageCount(account.Address, "test", 5);
            }
        }
        public void TestDistributionListAnnouncementFromDomainAlias()
        {
            var oIMAP = new IMAPClientSimulator();
            var oSMTP = new SMTPClientSimulator();

            Application application = SingletonProvider <TestSetup> .Instance.GetApp();


            //
            // TEST LIST SECURITY IN COMBINATION WITH DOMAIN NAME ALIASES
            //


            Account account = SingletonProvider <TestSetup> .Instance.AddAccount(_domain, "*****@*****.**", "test");

            var oRecipients = new List <string>();

            oRecipients.Add("*****@*****.**");

            DistributionList oList3 = SingletonProvider <TestSetup> .Instance.AddDistributionList(_domain, "*****@*****.**",
                                                                                                  oRecipients);

            oList3.Mode = eDistributionListMode.eLMAnnouncement;
            oList3.RequireSenderAddress = "*****@*****.**";
            oList3.Save();

            // THIS MESSAGE SHOULD FAIL
            CustomAssert.IsFalse(oSMTP.Send("*****@*****.**", "*****@*****.**", "Mail 1", "Mail 1"));

            DomainAlias oDA = _domain.DomainAliases.Add();

            oDA.AliasName = "dummy-example.com";
            oDA.Save();

            // THIS MESSAGE SHOULD SUCCEED
            CustomAssert.IsTrue(oSMTP.Send("*****@*****.**", "*****@*****.**", "Mail 1", "Mail 1"));
            IMAPClientSimulator.AssertMessageCount("*****@*****.**", "test", "Inbox", 1);
        }